diff --git a/src/NServiceBus.Core.Tests/MessageMapper/MessageMapperTests.cs b/src/NServiceBus.Core.Tests/MessageMapper/MessageMapperTests.cs index 043c380e05..aac7d3b5f0 100644 --- a/src/NServiceBus.Core.Tests/MessageMapper/MessageMapperTests.cs +++ b/src/NServiceBus.Core.Tests/MessageMapper/MessageMapperTests.cs @@ -46,16 +46,29 @@ public void CreateInstance_WhenMessageInitialized_ShouldBeThreadsafe() }); } +#if NETCOREAPP +#nullable enable [Test] public void Should_handle_messages_with_nullable_reference_types() { var mapper = new MessageMapper(); - // Type defined in separate assembly as a workaround - // because we can't use nullable refeference types yet - mapper.CreateInstance(); + mapper.CreateInstance(); } + public interface IMessageWithNullableProperties : NServiceBus.ICommand, NServiceBus.IMessage + { + string? NullableString { get; set; } + object[]? NullableArray { get; set; } + List? NullableList { get; set; } + } + + public class NullableComplexTypeItem + { + } +#nullable disable +#endif + [Test] public void CreateInstance_WhenMessageNotInitialized_ShouldBeThreadsafe() { @@ -253,5 +266,6 @@ public interface IMessageInterfaceWithNullablePropertyAttribute object Value { get; set; } } + } } \ No newline at end of file diff --git a/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj b/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj index 5dc39a8eea..ab6fb3483f 100644 --- a/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj +++ b/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj @@ -16,12 +16,6 @@ - - - - - - diff --git a/src/NServiceBus.Core.Tests/TestDlls/WithDodgyNullable.dll b/src/NServiceBus.Core.Tests/TestDlls/WithDodgyNullable.dll deleted file mode 100644 index f0570ea60f..0000000000 Binary files a/src/NServiceBus.Core.Tests/TestDlls/WithDodgyNullable.dll and /dev/null differ diff --git a/src/NServiceBus.Core/MessageInterfaces/MessageMapper/Reflection/ConcreteProxyCreator.cs b/src/NServiceBus.Core/MessageInterfaces/MessageMapper/Reflection/ConcreteProxyCreator.cs index 583ce24495..84e0c72587 100644 --- a/src/NServiceBus.Core/MessageInterfaces/MessageMapper/Reflection/ConcreteProxyCreator.cs +++ b/src/NServiceBus.Core/MessageInterfaces/MessageMapper/Reflection/ConcreteProxyCreator.cs @@ -2,6 +2,7 @@ namespace NServiceBus { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -99,26 +100,39 @@ static void AddCustomAttributeToProperty(CustomAttributeData attributeData, Prop { var namedArguments = attributeData.NamedArguments; + object[] constructorArgs = attributeData.ConstructorArguments.Select(ExtractValue).ToArray(); if (namedArguments == null) { var attributeBuilder = new CustomAttributeBuilder( attributeData.Constructor, - attributeData.ConstructorArguments.Select(x => x.Value).ToArray()); + constructorArgs); propBuilder.SetCustomAttribute(attributeBuilder); } else { + PropertyInfo[] namedProperties = namedArguments.Select(x => (PropertyInfo)x.MemberInfo).ToArray(); + object[] propertyValues = namedArguments.Select(x => x.TypedValue.Value).ToArray(); + var attributeBuilder = new CustomAttributeBuilder( attributeData.Constructor, - attributeData.ConstructorArguments.Select(x => x.Value).ToArray(), - namedArguments.Select(x => (PropertyInfo)x.MemberInfo).ToArray(), - namedArguments.Select(x => x.TypedValue.Value).ToArray()); + constructorArgs, + namedProperties, + propertyValues); propBuilder.SetCustomAttribute(attributeBuilder); } } + static object ExtractValue(CustomAttributeTypedArgument arg) + { + if (arg.Value is ReadOnlyCollection nestedValue) + { + return nestedValue.Select(x => x.Value).ToArray(); + } + return arg.Value; + } + /// /// Returns all properties on the given type, going up the inheritance hierarchy. ///