mardi 14 juillet 2015

How to invoke a generic method with weak-typed parameter

I've got a generic interface and bunch of classes which implement it. Here is a greatly simplified example:

interface IPrinter<in T>
{
    void Print(T args);
}

class IntPrinter : IPrinter<int>
{
    public void Print(int args)
    {
        Console.WriteLine("This is int: " +args);
    }
}

class StringPrinter : IPrinter<string>
{
    public void Print(string args)
    {
        Console.WriteLine("This is string: " + args);
    }
}

I also have a dictionary of those classes with generic argument's type as a key (I actually use reflection to populate it):

private readonly Dictionary<Type, object> Printers 
    = new Dictionary<Type, object>
        {
            {typeof (int), new IntPrinter()},
            {typeof (string), new StringPrinter()}
        };

Now I recive an instance of List<object> as an input, which contains a bunch of parameters of arbitrary type. For each parameter I want to pick the object, which implement an appropriate interface and call the print method. I am not sure how to implement that.

var args = new List<object> {1, "2"};
foreach (var arg in args)
{
    var printer = Printers[arg.GetType()];
    //how do I implement this mrthod so it calls ((IPrinter<T>)printer).Print((T)arg)?
    Print(printer, arg); 
}

I have tried

  1. Reflection. It works, but well... its reflection. I am looking for other ways to do it.

    private void Print(object printer, object arg)
    {
        printer.GetType().GetMethod("Print").Invoke(printer, new[] {arg});
    }
    
    
  2. Dynamic. A lot cleaner then reflection and usually faster. But for some reason it throws an exception if I use it with a type, which is private relative to executing assembly. Is this a known limitation of dynamic objects?

    private void Print(dynamic printer, dynamic arg)
    {
        printer.Print(arg);
    }
    
    
  3. Delegate. I was trying to use CreateDelegate method to create a some kind of weak-typed delegate from MethodInfo but i completely failed at that. Is it even possible?





Aucun commentaire:

Enregistrer un commentaire