动态委托和事件创建

本文关键字:事件 创建 动态 | 更新日期: 2023-09-27 18:14:50

我看到了以下问题在c#中动态生成委托类型和如何在c#中按类型创建动态委托对象?恐怕我还没有完全理解这些概念。

我试图解决的问题是:第三方库提供以下函数

AppendIncomingPacketHandler<incomingObjectType>(
    string packetTypeStr,
    NetworkComms.PacketHandlerCallBackDelegate<incomingObjectType> packetHandlerDelgatePointer)

AppendIncomingPacketHandler<incomingObjectType>(
    string packetTypeStr,
    NetworkComms.PacketHandlerCallBackDelegate<incomingObjectType> packetHandlerDelgatePointer,
    SendReceiveOptions options)

问题的第一部分是我需要为第一次调用动态创建处理程序,因为我只在运行时通过配置知道类型。我尝试使用反射,但我一直得到模棱两可的方法异常

问题的第二部分是,在动态生成的处理程序中,我需要为接收到的信息生成一个强类型事件。

问题的最后一部分是系统的另一部分必须连接起来接收强类型事件,这也是在运行时才知道的

感谢您的帮助。

我的反思尝试如下,我试图使用上面两个链接中的信息,以及一些谷歌从MethodInfo构建一个委托?和泛型方法使用运行时类型执行想办法去做

        MethodInfo method = typeof(Connection).GetMethod("AppendIncomingPacketHandler"); //this generates an ambigious method exception due to two functions being available
        MethodInfo generic = method.MakeGenericMethod(configuration.TypeToListenTo);
        Delegate.CreateDelegate(typeof(NetworkComms.PacketHandlerCallBackDelegate<>)) //cant figure out how to create the typed delegate and pass it to the right function.

我知道你可以在方法有歧义异常的情况下通过传递参数来指定调用哪个函数,但问题是上面看到的参数也需要类型化委托。

感谢阅读

//根据收到的评论构建代码,我有

        var methods = typeof(Connection).GetMethods();
        var functionOfInterest = methods[21];
        var genericDelegate = typeof(NetworkComms.PacketHandlerCallBackDelegate<>);
        var constructedDelegate = genericDelegate.MakeGenericType(new Type[] { configuration.TypeToListenTo });
        DisplayTypeInfo(constructedDelegate);
        var mappedMethod  = functionOfInterest.MakeGenericMethod(configuration.TypeToListenTo);
        mappedMethod.Invoke(CommunicationLink,
            new object[] {configuration.TypeToListenTo.ToString(), constructedDelegate});

我现在得到这个异常在mappedMethod调用…

System类型的对象。RuntimeType'不能转换为类型'NetworkCommsDotNet.NetworkComms+PacketHandlerCallBackDelegate ' 1[networkcommunicationtest . program +Test]

///再考虑一下

    var methods = typeof(Connection).GetMethods();
    var functionOfInterest = methods[21];
    var genericDelegate = typeof(NetworkComms.PacketHandlerCallBackDelegate<>);
    var constructedDelegate = genericDelegate.MakeGenericType(new Type[] { configuration.TypeToListenTo });
    //Delegate.CreateDelegate(constructedDelegate, func);
    DisplayTypeInfo(constructedDelegate);
    var mappedMethod = functionOfInterest.MakeGenericMethod(configuration.TypeToListenTo);
    var dynamicMethod = new DynamicMethod("dataHandler", null,
        new Type[] {typeof (PacketHeader), typeof (Connection), configuration.TypeToListenTo});
    ILGenerator il = dynamicMethod.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0); //random il just to test the concept
    il.Emit(OpCodes.Conv_I8); //random il just to test the concept
    il.Emit(OpCodes.Dup); //random il just to test the concept
    il.Emit(OpCodes.Mul); //random il just to test the concept
    il.Emit(OpCodes.Ret); //random il just to test the concept
    mappedMethod.Invoke(CommunicationLink,
        new object[] { configuration.TypeToListenTo.ToString(), dynamicMethod.CreateDelegate(constructedDelegate) });

我讲对了吗?

我写了下面的代码,希望能更好地说明我想要实现的目标,感兴趣的部分被注释掉了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var thirdPartyConsumer = new ThirdPartyConsumer();
            thirdPartyConsumer.Start(typeof(string));
            var eventSubscriber = new EventSubscriber(thirdPartyConsumer, typeof (string));
        }
        public class ThirdParty
        {
            public delegate void CallBackDelegate<incomingObjectType>(incomingObjectType incomingObject);
            public delegate void CallBackSubscriberDelegate<incomingObjectType>();
            public void RegisterHandler<incomingType>(string name, CallBackDelegate<incomingType> callback)
                where incomingType : new()
            {
                Console.WriteLine("Registered type is {0}", typeof(incomingType));
                callback.Invoke(new incomingType());
            }
            public void RegisterSubscriber<incomingType>(string name, CallBackSubscriberDelegate<incomingType> callback)
            {
                Console.WriteLine("Registered type is {0}", typeof(incomingType));
                callback.Invoke();
            }
        }
        public class ThirdPartyConsumer
        {
            public void Start(Type dataType)
            {
                var thirdParty = new ThirdParty();
                // want to create a typed delegate to invoke the instance Callback<T> method
                //thirdParty.RegisterHandler(dataType.ToString(),Callback<dataType>); 
                // want to create a typed delegate to invoke the instance Callback<T> method
                //thirdParty.RegisterSubscriber(dataType.ToString(), Callback<dataType>);

                //want to create a public eventhandler on this object which is typed to datatype
                //CreateTypedEventHandler(dataType);
            }
            private void Callback()
            {
                Console.WriteLine("Called Callback");
            }

            private void Callback<T>(T incomingType)
            {
                Console.WriteLine("Called Generic Callback");
            }
        }
        public class EventSubscriber
        {
            public EventSubscriber(ThirdPartyConsumer consumer,Type  type)
            {
                //want to wire the dynamically created/added event handler
               //consumer.TypedEventHandler += ReceivedEvent();
            }
            private void ReceivedEvent<T>(T data)
            {
                Console.WriteLine("Event received of type {0}", typeof(T));
            }
        }
    }
}

//////有了安东的反馈,我现在得到了这个。这些方法在性能方面有什么问题吗?有更好的方法吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var genericType = typeof(ThirdPartyConsumer<>);
            Type constructedGenericType = genericType.MakeGenericType(new Type[] { typeof(string) });
            var constructed = Activator.CreateInstance(constructedGenericType);
            MethodInfo castMethod = typeof(Utils).GetMethod("Cast").MakeGenericMethod(constructedGenericType);
            var cast = castMethod.Invoke(null, new object[] { constructed });
            var eventSubscriber = new EventSubscriber();
            MethodInfo subscribeMethod = typeof(EventSubscriber).GetMethod("Subscribe").MakeGenericMethod(new Type[] { typeof(string) });
            subscribeMethod.Invoke(eventSubscriber, new object[] { cast });
        }
        public class ThirdParty
        {
            public delegate void CallBackDelegate<incomingObjectType>(incomingObjectType incomingObject);
            public delegate void CallBackSubscriberDelegate<incomingObjectType>();
            public void RegisterHandler<incomingType>(string name, CallBackDelegate<incomingType> callback)
                where incomingType : new()
            {
                Console.WriteLine("Registered type is {0}", typeof(incomingType));
                callback.Invoke(new incomingType());
            }
            public void RegisterSubscriber<incomingType>(string name, CallBackSubscriberDelegate<incomingType> callback)
            {
                Console.WriteLine("Registered type is {0}", typeof(incomingType));
                callback.Invoke();
            }
        }
        public class ThirdPartyConsumer<T>
        {
            public event Action<T> TypedEventHandler;
            public void Start<T>() where T : new()
            {
                var thirdParty = new ThirdParty();
                // want to create a typed delegate to invoke the instance Callback<T> method
                thirdParty.RegisterHandler<T>(typeof(T).ToString(), Callback<T>);
                // want to create a typed delegate to invoke the instance Callback<T> method
                //thirdParty.RegisterSubscriber<T>(typeof (T).ToString(), Callback<T>);
            }

            private void Callback<T>(T incomingType)
            {
                Console.WriteLine("Called Generic Callback");
            }
        }
        public class EventSubscriber
        {
            public EventSubscriber()
            {
            }
            public void Subscribe<T>(ThirdPartyConsumer<T> consumer)
            {
                consumer.TypedEventHandler += consumer_TypedEventHandler;
            }
            void consumer_TypedEventHandler<T>(T obj)
            {
            }

        }
        public static class Utils
        {
            public static T Cast<T>(object o)
            {
                return (T)o;
            }
        }
    }
}

动态委托和事件创建

我选择了@Anton建议的路线,这是问题中的最后一个例子。随着fasterreflect和动态关键字的明智使用以及代码的非通用和通用部分的单独接口,我已经有了一个工作解决方案,它的工作速度足以满足我的需求。

感谢大家阅读