2011-11-26 47 views
0

我在写流水线逻辑。这个想法是在实例中创建对象并在每种情况下执行Run方法。我可以用反射Activator.CreateInstance做旧的方式很容易,但在这种情况下性能很重要。LINQ动态创建对象没有反射(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 */ 
    } 
} 

}

回答

0

这应该工作:我已经直接提供给newExp和invokeExpression左arguments作为其唯一的参数

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

通知。

+0

它仍然抛出异常“参数计数不匹配”,请尝试上面的控制台演示。感谢Damir的努力! – JBaltika

+0

此外,如果我更改为下面的代码,它的作品。我正在用Expression.New(type)做的事情不对。 var newinstance = System.Activator.CreateInstance(type); func.DynamicInvoke(newinstance,arguments); – JBaltika

+0

我试过我的示例,它的工作原理。你错过了我为'委托func'行做的改变 - 我在那里删除了一个参数。 问题的确是'Expression.New(type)':它是一个'Expression',但你需要提供一个实例作为lambda的参数。这就是为什么它可以使用'CreateInstance()'。它也可以像这样工作:'func.DynamicInvoke(Expression.Lambda(newExp).Compile().DynamicInvoke(),arguments)',但像上面所做的那样将它保留在单个表达式中效率更高。 –

相关问题