1

我正在使用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

4 回答 4

2

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

  Type type=someFunction.GetType();

现在获取Invoke成员:

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

这是执行委托时实际调用的方法。您可以调用GetParametersmethodInfo 来了解它需要多少个参数。

如果您已经知道要添加多少个参数以及它们的类型,那么事情就容易多了。您只需分配给一个代表并调用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);
}
于 2013-04-22T14:24:55.417 回答
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);

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

于 2013-04-22T15:00:23.910 回答
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");
   }
}

然后只需调用 Magic(1, 2); 或魔法(1,2,3);

于 2013-04-22T15:38:29.053 回答
0

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

据我了解,您想要获得的是具有特定签名的方法列表:它必须是返回double和接收 2的方法integers?那么您可能应该将 (!) aList<>作为返回 (!) 值返回吗?

第二:不可能将所有方法都放入特定的Func<>orAction<>或 else 中。自然有些函数会列出不同的输入参数和不同的返回值。对 ?因此,如果 (!) 您只想处理返回double和接收 2的函数,integers那么List<>对于这些​​类型的方法,只会返回 (!)。请阅读有关函数签名的更多信息

第三:我猜这是对 MEF 的错误使用。基本上 MEF 的意思是:在你的应用程序中定义接口,使用它就像它是用它创建的一样new,我 (MEF) 将在运行时插入它。所以实际上你不需要获取任何方法的列表。只需确保双方都支持/定义/继承这些方法并像在您的应用程序中定义它们一样使用它们

于 2013-04-22T14:21:48.060 回答