Dictionary of Action Delegates

后端 未结 2 954
滥情空心
滥情空心 2020-12-06 02:29

I have object XML serialized messages coming into a class called MessageRouter. The XML contains the Type name it it was serialized from, a

2条回答
  •  [愿得一人]
    2020-12-06 02:33

    You cannot do this as described, for quite obvious reasons - even if somehow allowed, the last line of code in your example (the one which retrieves a delegate and then calls it) would be non-typesafe, as you're calling an Action - which expects T as an argument - and yet passing it deserializedObject, which is of type object. It wouldn't work in plain code without a cast, why would you expect to be able to circumvent the type check for your case?

    In the simplest case, you can do something like this:

    Dictionary registeredDelegates;
    ...
    registeredDelegates[xmlSerializedType].DynamicInvoke(deserializedObject);
    

    Of course this will allow someone to add a delegate which takes more or less than one argument to the dictionary, and you'll only find out at DynamicInvoke call, at run-time. But there isn't really any way to define a type which says "any delegate, but with 1 argument only". A better option might be this:

    Dictionary> registeredDelegates
    

    and then registering types like this:

    myMessageRouter.RegisterDelegateForType(
       o => myActionHandler((MySerializableType)o)
    );
    

    The above snippet uses C# 3.0 lambdas, but you can do the same - if slightly more verbose - with C# 2.0 anonymous delegates. Now you don't need to use DynamicInvoke - the lambda itself will do the proper cast.

    Finally, you can encapsulate the lambda creation into RegisterDelegateForType itself by making it generic. For example:

    private Dictionary> registeredDelegates;
    
    void RegisterDelegateForType(Action d)
    {
        registeredDelegates.Add(typeof(T), o => d((T)o));
    }
    

    And now the callers can just do:

    RegisterDelegateForType(myHandler)
    

    So it's completely typesafe for your clients. Of course, you're still responsible for doing it right (i.e. passing an object of the correct type to the delegate you retrieve from the dictionary).

提交回复
热议问题