Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 行动字典<;T>;代表_C#_.net_Generics - Fatal编程技术网

C# 行动字典<;T>;代表

C# 行动字典<;T>;代表,c#,.net,generics,C#,.net,Generics,我将对象XML序列化消息放入名为MessageRouter的类中。XML包含从中序列化的类型名称,我需要能够调用不同的委托方法,这取决于运行时之前未知的类型。我不是特别擅长泛型,所以希望这对某些人来说是有意义的 我希望MessageRouter提供一个RegisterDelegateForType方法,如下所示: myMessageRouter.RegisterDelegateForType(new Action<MySerializableType>(myActionHandler

我将对象XML序列化消息放入名为MessageRouter的类中。XML包含从中序列化的类型名称,我需要能够调用不同的委托方法,这取决于运行时之前未知的类型。我不是特别擅长泛型,所以希望这对某些人来说是有意义的

我希望MessageRouter提供一个RegisterDelegateForType方法,如下所示:

myMessageRouter.RegisterDelegateForType(new Action<MySerializableType>(myActionHandler));
因此,我的问题是:

  • 如何定义一个字典,其中可以包含一个
    类型
    作为键,一个泛型
    操作
    作为值,并让RegisterDeleteGateForType方法填充字典
  • 如果不可能,那么最好的方法是什么

  • 您不能按描述的那样执行此操作,原因很明显-即使允许,示例中的最后一行代码(检索委托然后调用它的代码)将是非类型安全的,因为您正在调用
    操作
    -该操作期望
    T
    作为参数-但将其传递给
    反序列化对象
    ,类型为
    对象
    。如果没有强制转换,它无法在普通代码中工作,为什么您希望能够绕过您的案例的类型检查

    在最简单的情况下,您可以执行以下操作:

    Dictionary<Type, Delegate> registeredDelegates;
    ...
    registeredDelegates[xmlSerializedType].DynamicInvoke(deserializedObject);
    
    然后注册如下类型:

    Dictionary<Type, Action<T>> registeredDelegates;
    
    myMessageRouter.RegisterDelegateForType<MySerializableType>(
       o => myActionHandler((MySerializableType)o)
    );
    
    现在,呼叫者只需执行以下操作:

    RegisterDelegateForType<MySerializableType>(myHandler)
    
    RegisterDelegateForType(myHandler)
    

    所以对你的客户来说是完全安全的。当然,您仍有责任正确地执行此操作(即,将正确类型的对象传递给从字典中检索到的委托)。

    我不确定这是否完全回答了您的问题,但我编写的一个类将实现您想要的功能。我无法判断您是否希望动作委托接受类型化对象,但在伪代码中,您向其传递了一个“对象”进行反序列化,因此我编写了相应的类,因此它不使用泛型:

    public delegate void Action(object o);
    
    public class DelegateDictionary {
        private IDictionary _dictionary = new Hashtable();
    
        public void Register<T>(Action action) {
            _dictionary[typeof(T)] = action;
        }
    
        public Action Get<T>() {
            return (Action)_dictionary[typeof(T)];
        }
    
        public static void MyFunc(object o) {
            Console.WriteLine(o.ToString());
        }
    
        public static void Run() {
            var dictionary = new DelegateDictionary();
            dictionary.Register<string>(MyFunc);
            // Can be converted to an indexer so that you can use []'s
            var stringDelegate = dictionary.Get<string>();
            stringDelegate("Hello World");
        }
    }
    
    公共委托无效操作(对象o);
    公共类委派字典{
    私有IDictionary_dictionary=新哈希表();
    公共无效登记册(行动){
    _字典[类型(T)]=动作;
    }
    公共行动{
    返回(动作)_字典[typeof(T)];
    }
    公共静态void MyFunc(对象o){
    Console.WriteLine(o.ToString());
    }
    公共静态无效运行(){
    var dictionary=新的DelegateDictionary();
    字典寄存器(MyFunc);
    //可以转换为索引器,以便您可以使用[]
    var stringDelegate=dictionary.Get();
    stringDelegate(“你好,世界”);
    }
    }
    

    我相信这将实现您想要的功能。

    为什么不将IDictionary作为字典呢?我想我正在等待routeNpingme是否需要支持void Action(T)的委托类型;如果是这样的话,您就不能使用字典,而这个设计可以很容易地修改以支持它。如果没有,那么是的,最好是一本字典。即使他需要支持行动,如果我使用字典,设计会更好。
    private Dictionary<Type, Action<object>> registeredDelegates;
    
    void RegisterDelegateForType<T>(Action<T> d)
    {
        registeredDelegates.Add(typeof(T), o => d((T)o));
    }
    
    RegisterDelegateForType<MySerializableType>(myHandler)
    
    public delegate void Action(object o);
    
    public class DelegateDictionary {
        private IDictionary _dictionary = new Hashtable();
    
        public void Register<T>(Action action) {
            _dictionary[typeof(T)] = action;
        }
    
        public Action Get<T>() {
            return (Action)_dictionary[typeof(T)];
        }
    
        public static void MyFunc(object o) {
            Console.WriteLine(o.ToString());
        }
    
        public static void Run() {
            var dictionary = new DelegateDictionary();
            dictionary.Register<string>(MyFunc);
            // Can be converted to an indexer so that you can use []'s
            var stringDelegate = dictionary.Get<string>();
            stringDelegate("Hello World");
        }
    }