Explorar o código

Add MessageUtil.RegisterMessageType

Lucas Trzesniewski %!s(int64=5) %!d(string=hai) anos
pai
achega
ad28a4b125

+ 35 - 1
src/Abc.Zebus.Tests/MessageUtilTests.cs

@@ -1,6 +1,8 @@
-extern alias senderVersion;
+extern alias senderVersion;
 using System;
 using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
 using Abc.Zebus.Testing.Extensions;
 using NUnit.Framework;
 
@@ -87,6 +89,38 @@ namespace Abc.Zebus.Tests
             Assert.Throws<InvalidOperationException>(() => MessageUtil.GetTypeId(typeof(GenericEvent<List<string>>)));
         }
 
+        [Test]
+        public void should_resister_message_type()
+        {
+            var typeA = GenerateType(true);
+            var typeB = GenerateType(false);
+
+            typeB.FullName.ShouldEqual(typeA.FullName);
+
+            MessageUtil.RegisterMessageType(typeA);
+            new MessageTypeId(typeA).IsPersistent().ShouldBeTrue();
+
+            MessageUtil.RegisterMessageType(typeB);
+            new MessageTypeId(typeB).IsPersistent().ShouldBeFalse();
+
+            static Type GenerateType(bool persistent)
+            {
+                var moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString("N")), AssemblyBuilderAccess.Run)
+                                                   .DefineDynamicModule("Main");
+
+                var typeBuilder = moduleBuilder.DefineType(
+                    "GeneratedMessageType",
+                    TypeAttributes.AutoClass | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.NotPublic | TypeAttributes.Sealed,
+                    typeof(object)
+                );
+
+                if (!persistent)
+                    typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(TransientAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>()));
+
+                return typeBuilder.CreateType();
+            }
+        }
+
         public class GenericEvent<T> : IEvent
         {
         }

+ 6 - 0
src/Abc.Zebus/MessageTypeDescriptorCache.cs

@@ -41,5 +41,11 @@ namespace Abc.Zebus
             var fullName = TypeUtil.GetFullNameWithNoAssemblyOrVersion(messageType);
             return GetMessageTypeDescriptor(fullName);
         }
+
+        internal static void Remove(Type messageType)
+        {
+            _descriptorsByType.TryRemove(messageType, out _);
+            _descriptorsByFullName.TryRemove(TypeUtil.GetFullNameWithNoAssemblyOrVersion(messageType), out _);
+        }
     }
 }

+ 11 - 0
src/Abc.Zebus/MessageUtil.cs

@@ -1,4 +1,5 @@
 using System;
+using Abc.Zebus.Util;
 
 namespace Abc.Zebus
 {
@@ -18,5 +19,15 @@ namespace Abc.Zebus
         {
             return new MessageTypeId(messageType);
         }
+
+        /// <summary>
+        /// Useful for advanced scenarios where a given type name is loaded multiple times.
+        /// Makes sure the right type is used.
+        /// </summary>
+        public static void RegisterMessageType(Type messageType)
+        {
+            TypeUtil.Register(messageType);
+            MessageTypeDescriptorCache.Remove(messageType);
+        }
     }
 }

+ 4 - 3
src/Abc.Zebus/Util/TypeUtil.cs

@@ -12,9 +12,10 @@ namespace Abc.Zebus.Util
         private static readonly ConcurrentDictionary<string, Type?> _typesByNames = new ConcurrentDictionary<string, Type?>();
 
         public static Type? Resolve(string typeName)
-        {
-            return _typesByNames.GetOrAdd(typeName, FindTypeByName);
-        }
+            => _typesByNames.GetOrAdd(typeName, FindTypeByName);
+
+        public static void Register(Type type)
+            => _typesByNames[GetFullNameWithNoAssemblyOrVersion(type)] = type;
 
         private static Type? FindTypeByName(string typeName)
         {