没有反射(Activator.CreateInstance)和方法调用的LINQ动态对象创建

没有反射(Activator.CreateInstance)和方法调用的LINQ动态对象创建,linq,reflection,lambda,expression-trees,activator,Linq,Reflection,Lambda,Expression Trees,Activator,我在写管道逻辑。其思想是动态创建对象的实例,并在每种情况下执行方法Run方法。使用reflections Activator.CreateInstance,我可以很容易地使用旧方法,但在这种情况下,性能很重要 我看了很多代码示例和教程,我想我正确地理解了Lambda表达式。我只能找出调用部分。提前谢谢 namespace Pipelines { using System; using System.Linq; using System.Linq.Expressions; using System

我在写管道逻辑。其思想是动态创建对象的实例,并在每种情况下执行方法Run方法。使用reflections Activator.CreateInstance,我可以很容易地使用旧方法,但在这种情况下,性能很重要

我看了很多代码示例和教程,我想我正确地理解了Lambda表达式。我只能找出调用部分。提前谢谢

namespace Pipelines
{
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public interface IProcessor
{
    string Name { get; set; }
}

public interface IAspNetMembershipId : IProcessor
{
    Guid? Id { get; set; }
}

public class ProcessorOne
{
    public void Run(IProcessor args)
    {
        /* Do Something */
    }
}

public class ProcessorTwo
{
    public void Run(IAspNetMembershipId args)
    {
        /* Do Something */
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var arguments = new AspNetMembershipId() { Name = "jim" };

        /* Pipeline1 Begin */
        Type type = typeof(ProcessorOne);
        NewExpression newExp = Expression.New(type);

        var p1 = Expression.Parameter(newExp.Type, "ProcessorOne");
        var p2 = Expression.Parameter(typeof(IProcessor), "args");

        MethodInfo methodInfo = (from method in newExp.Type.GetMethods() where method.Name.StartsWith("Run") select method).First();
        var invokeExpression = Expression.Call(p1, methodInfo, p2);

        Delegate func = Expression.Lambda(invokeExpression, p1, p2).Compile();

        /* Throws an exception. This not correct! */
        func.DynamicInvoke(newExp, arguments);
        /* or */
        func.DynamicInvoke(arguments);

        /* Pipeline2 Begin */
    }
}
}

这应该可以:

var arguments = new AspNetMembershipId() { Name = "jim" };

/* Pipeline1 Begin */
Type type = typeof(ProcessorOne);

NewExpression newExp = Expression.New(type);

var p2 = Expression.Parameter(typeof(IProcessor), "args");

MethodInfo methodInfo = (from method in newExp.Type.GetMethods()
                            where method.Name.StartsWith("Run")
                            select method).First();

var invokeExpression = Expression.Call(newExp, methodInfo, p2);
Delegate func = Expression.Lambda(invokeExpression, p2).Compile();

/* Doesn't throw exception any more */
func.DynamicInvoke(arguments);

请注意,我直接向invokeExpression提供了newExp,并将参数作为其唯一参数

它仍然抛出异常参数计数不匹配,请尝试上面的控制台演示。谢谢你的努力,达米尔!如果我改为下面的代码,它也会工作。我正在用表达式做一些事情。新类型不正确。var newinstance=System.Activator.CreateInstancetype;func.DynamicInvokenewinstance,参数;我试了试我的样品,效果很好。您错过了我对委托func行所做的更改-我在那里删除了一个参数。问题确实出在表达式上。Newtype:它是一个表达式,但需要提供一个实例作为lambda的参数。这就是为什么它与CreateInstance一起工作。它的工作原理也是这样的:func.DynamicInvokeExpression.lambdanewxp.Compile.DynamicInvoke,arguments,但像我上面所做的那样,将其保存在一个表达式中更有效。@juozasbortikauskas我还对使用反射相比实际的性能提升感到好奇。缓存编译后的表达式可能会有所帮助……性能测试是我列表中的下一个测试。我想比较两个版本。据我在博客上读到的,4.0框架的“Activator”性能在5月份达到200倍。