调用Func<比;与参数

本文关键字:参数 Func 调用 | 更新日期: 2023-09-27 18:10:16

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

调用Func<比;与参数

一旦你得到了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实例。someFuncInstance是你从某处得到的Func<>的一个实例。

对于你的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);
}

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

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

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

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

我猜你超载了Func<>接口…

正如我所理解的,你想要得到的是一个具有特定签名的方法列表:它必须是返回double并接收2 integers的方法?所以也许你应该返回(!)一个List<>作为返回(!)值?

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

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