Search code examples
c#mef

Invoke Func<> with parameters


I am importing methods with MEF. I call this method to get all exported methods:

var methods = container.GetExports<Func<int,int,double>,MyMetadata>("contract name");

NOTE: Sometimes Func<int,int,double> changes. For example it might have more parameters: Func<int,int,int,double>.

When I fire methods I know how many parameters to pass. My question is how can I dynamically pass parameters to imported methods?

UPDATE:

    IEnumerable<Lazy<Func<int,int,double>,MyMetadata>> Plugins; 
    public IEnumerable RunAllPlugins(int a, int b)
    {
        //my old approach
        foreach (var p in Plugins)
        {
            dynamic a = p;
            var b = a.Value.Invoke(a,b); //here I want to pass parameters dynamically
        }
        //this is new approach which is answer
        //now I can pass parameters like array of objects
        foreach(var lazyMethod in Plugins)
        {
            Delegate d=lazyMethod.Value;
            object[] numbers=new object[]{1,2};
            var result=d.DynamicInvoke(numbers);
        }
        return null;
    }

Solution

  • Once you've got the Func<> get its type:

      Type type=someFunction.GetType();
    

    Now get the Invoke member:

      var methodInfo=type.GetMember("Invoke");
    

    This is the method that is actually called when you execute the delegate. You can call GetParameters on the methodInfo to find out how many parameters it takes.

    If you already know how many parameters to add, and their type, then things are easier. You just assign to a delegate and call DynamicInvoke:

        Delegate d=someFuncInstance;
        object[] numbers=new object[]{1,2};
        var result=d.DynamicInvoke(numbers);
    

    result will be an object instance which you'll need to cast. someFuncInstance is an instane of Func<> that you've gotten hold of from somewhere.

    So, for you MEF example it'd be something like this:

    var methods=container.GetExports<Func<int,int,double>,MyMetadata>("contract name");
    foreach(var lazyMethod in methods)
    {
      Delegate d=lazyMethod.Value;
      object[] numbers=new object[]{1,2};
      var result=d.DynamicInvoke(numbers);
    }