调用Func<>带参数

时间:2013-04-22 14:11:50

标签: c# mef

我正在使用MEF导入方法。我将此方法称为获取所有导出的方法:

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

注意:有时Func<int,int,double>会发生变化。例如,它可能包含更多参数:Func<int,int,int,double>

当我触发方法时,我知道要传递多少参数。 我的问题是如何动态地将参数传递给导入的方法?

更新:

    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;
    }

4 个答案:

答案 0 :(得分:2)

一旦你得到Func<>得到它的类型:

  Type type=someFunction.GetType();

现在获取Invoke成员:

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

这是执行委托时实际调用的方法。您可以在methodInfo上调用GetParameters以查找它需要多少参数。

如果您已经知道要添加多少参数及其类型,那么事情就更容易了。您只需分配给代理人并致电DynamicInvoke

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

result将是您需要投射的object个实例。 someFuncInstanceFunc<>的一个你从某个地方得到的东西。

所以,对你来说MEF的例子就是这样:

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);
}

答案 1 :(得分:1)

methods的类型应为IEnumerable<Lazy<Func<int,int,double>>,所以简单

 foreach(var method in methods)
 {
      method.Value(a,b);
 }

应该有效。或者如果您想将其保存以供日后使用:

Func<int,int,double> mySavedDelegate = methods.First();

//...

mySavedDelegate(a,b);

编辑:更好的做法是导出接口并从导入的接口执行所需的方法,而不是直接导出方法。我从来没有做过后者,但从你的问题开始假设它首先是可能的。

答案 2 :(得分:1)

变量函数应该在这里工作。

double Magic(params int[] args)
{
   switch(args.Count)
   {
     case 2: return args[0]+args[1];
     case 3: return args[0]+args[1]/args[3];
     default: throw new Exception("Not supported");
   }
}

然后打电话 魔术(1,2); 要么 魔法(1,2,3);

答案 3 :(得分:0)

我猜你超载了Func<>界面......

据我所知,您想要获得的是具有特定签名的方法列表:它必须是返回double并接收2 integers的方法?那你可能应该返回(!)一个List<>作为return(!)值吗?

第二:不可能将所有方法都放在特定的Func<>Action<>或其他方面。当然,一些函数会列出输入的不同参数和不同的返回值。对 ?因此,如果(!)您只想处理返回double并接收2 integers的函数,那么List<>将只返回(!)这些类型的方法。请阅读功能签名

的更多信息 第三:我想这是对MEF的错误使用。基本上MEF所说的是:在应用程序中定义界面,使用它就好像它是用new创建的一样,而我(MEF)会在运行时插入它。所以实际上你并不需要 来获取任何方法的列表。只需确保双方都支持/定义/继承这些方法并使用它们就像在应用程序中定义它们一样