-
Notifications
You must be signed in to change notification settings - Fork 649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MessageMapper.Initialize NullReferenceException due to incorrect treatment of generic types #1737
Comments
To avoid the issue I removed the generic base class and implemented a generic interface. The hope was, that the bus is not trying to create an instance of an interface. Nope, the MessageMapper is not tested well so I have now another exception
|
@MBabi are you able to provide us with a failing unit test? |
Hi John I think the fix is simple. All you need to change is to add the similar condition like in the ConfigUnicastBus.IsMessageHandler method. Here the corrected version of IsMessageType /// <summary>
/// Returns true if the given type is a message type.
/// </summary>
public static bool IsMessageType(Type t)
{
try
{
if (t.IsGenericTypeDefinition)
{
return false;
}
return MessagesConventionCache.ApplyConvention(t,
type => IsMessageTypeAction(type) ||
IsCommandTypeAction(type) ||
IsEventTypeAction(type) ||
IsInSystemConventionList(type));
}
catch (Exception ex)
{
throw new MessageConventionException("Failed to evaluate Message convention. See inner exception for details.", ex);
}
} The other options is to fix it directory in the MessageMapper.cs old new
... ... @@ -53,7 +53,7 @@ public void InitType(Type t, ModuleBuilder moduleBuilder)
53 53 return;
54 54 }
55 55
56 - if (t.IsSimpleType())
56 + if (t.IsSimpleType() || t.IsGenericTypeDefinition)
57 57 {
58 58 return;
59 59 }
... ... @@ -339,7 +339,7 @@ public Type GetMappedTypeFor(Type t)
339 339 {
340 340 Type result;
341 341 concreteToInterfaceTypeMapping.TryGetValue(t, out result);
342 - if (result != null)
342 + if (result != null || t.IsGenericTypeDefinition)
343 343 {
344 344 return result;
345 345 } Here some tests to reproduce the issue: namespace NServiceBus.MessageInterfaces.Tests
{
using NUnit.Framework;
[TestFixture]
public class When_mapping_usinggenerics
{
IMessageMapper mapper;
[SetUp]
public void SetUp()
{
mapper = new MessageMapper.Reflection.MessageMapper();
}
[Test]
public void Class_abstract_generic_with_only_properties_generic_should_not_be_mapped()
{
var genericClassType = typeof(GenericAbstractCommand<>);
mapper.Initialize(new[] { genericClassType });
Assert.Null(mapper.GetMappedTypeFor(genericClassType));
}
[Test]
public void Class_generic_with_only_properties_generic_should_not_be_mapped()
{
var abstractClassType = typeof(GenericCommand<>);
mapper.Initialize(new[] { abstractClassType });
Assert.Null(mapper.GetMappedTypeFor(abstractClassType));
}
[Test]
public void Class_derived_from_generic_with_only_properties_generic_should_be_mapped()
{
var abstractClassType = typeof(DerivedGenericCommand);
mapper.Initialize(new[] { abstractClassType });
Assert.NotNull(mapper.GetMappedTypeFor(abstractClassType));
}
[Test]
public void Class_concrete_generic_with_only_properties_generic_should_be_mapped()
{
var abstractClassType = typeof(GenericCommand<Data>);
mapper.Initialize(new[] { abstractClassType });
Assert.NotNull(mapper.GetMappedTypeFor(abstractClassType));
}
[Test]
public void Class_abstract_with_only_properties_should_be_mapped()
{
var abstractClassType = typeof(SimpleAbstractClass);
mapper.Initialize(new[] { abstractClassType });
Assert.NotNull(mapper.GetMappedTypeFor(abstractClassType));
}
[Test]
public void Class_abstract_with_methods_should_not_be_mapped()
{
var abstractClassType = typeof(SimpleAbstractClassWithMethods);
mapper.Initialize(new[] { abstractClassType });
Assert.Null(mapper.GetMappedTypeFor(abstractClassType));
}
[Test]
public void Interfaces_generic_with_only_properties_should_not_be_mapped()
{
var genericInterfaceType = typeof(InterfaceGenericWithProperties<>);
mapper.Initialize(new[] { genericInterfaceType });
Assert.Null(mapper.GetMappedTypeFor(genericInterfaceType));
}
[Test]
public void Interfaces_generic_with_methods_should_not_be_mapped()
{
var genericInterfaceType = typeof(InterfaceGenericWithMethods<>);
mapper.Initialize(new[] { genericInterfaceType });
Assert.Null(mapper.GetMappedTypeFor(genericInterfaceType));
}
[Test]
public void Interfaces_with_only_properties_should_be_mapped()
{
var simpleInterfaceType = typeof(InterfaceWithProperties);
mapper.Initialize(new[] { simpleInterfaceType });
Assert.NotNull(mapper.GetMappedTypeFor(simpleInterfaceType));
}
}
public abstract class Data
{
}
public interface InterfaceGenericWithProperties<T> : IMessage where T : Data
{
string SomeProperty { get; set; }
T MessageProperty { get; set; }
}
public interface InterfaceGenericWithMethods<in T> : IMessage where T : Data
{
string SomeProperty { get; set; }
void MethodOnInterface(T myMessage);
}
public abstract class GenericAbstractCommand<T> : IMessage where T : Data
{
public T DataToTransfer { get; set; }
}
public class GenericCommand<T> : IMessage where T : Data
{
public T DataToTransfer { get; set; }
}
public class DerivedGenericCommand : GenericAbstractCommand<Data>
{
}
public interface InterfaceSimplWithProperties : IMessage
{
string SomeProperty { get; set; }
}
public abstract class SimpleAbstractClass : IMessage
{
string SomeProperty { get; set; }
}
public abstract class SimpleAbstractClassWithMethods : IMessage
{
string SomeProperty { get; set; }
protected abstract void DoTest();
}
} |
Can you please send us a PR instead? On Saturday, November 9, 2013, Marinko wrote:
Regards |
GenericTypeDefintions can't be mapped except we use constraints
issue #1737 NullReferenceException MessageMapper
If in the domain the following abstract class is defined, the bus will during the startup cause a NullReferenceException
The problem here is when the method
GetTypeName(Type t)
gets the property T TaskData as input, thet.FullName
is then null. ContainsKey using null causes the exception. Here the stacktraceJust to make it clear, I can't actually go on with the development, because the bus is not able to start.
The minimum I expect is to check for abstract classes, because it makes no sense to map them. This should be an easy fix.
The text was updated successfully, but these errors were encountered: