2014-07-08 55 views
1

我想用C#中某种类型的Lambda表达式返回方法(或方法信息)。MemberExpression是否可以返回方法

public class MyClass { 
    public object ReturnSomething(string arg, int numericArg) 
    {/*...*/} 
} 

然后,后来,我想引用使用Lambda像这样这个方法..

public static void Run<T>(T sourceObject, Expression<Func<T, object>> memberExpression, IEnumerable<object> parameters) 
{ 
    var methodInfo = ((MemberExpression)memberExpression.Body).Member as MethodInfo; 
    if (methodInfo == null) 
     throw new ArgumentException("memberExpression must yield a method"); 
    /*...*/ 
} 

我已经使用这个具有类似的尝试:

var myClassObject = new MyClass(); 
Run(myClassObject, o => o.ReturnSomething, new object["string arg", 1]); 

但我不断收到我的表达式编译器错误:

无法将方法组'ReturnSomething'转换为非委托类型 'object'。你打算采用这种方法吗?

这是在c#中可行吗?或者我应该放弃并传递一个字符串的方法名称并使用反射来查找而不是使用MemberExpression?

+0

不能说我明白了点吧,为什么你需要这样做?动态执行的要点是允许非编码源驱动执行,这种方法要求您提供方法和参数。我错过了什么? –

回答

0

T McKeown问上述正确的问题,当我很容易地在我的lambda表达式中提供参数时,我中途使用了动态执行。

我解决了这个问题,而不是做愚蠢的东西..而不是返回实际的方法,我改变了结构为我们一个执行内联执行的表达式。看起来比我最初去的地方清洁得多。

意图是比较两个类似分类对象的执行情况,以确保它们都返回相同的值。这是因为我处于重写过程中,并希望确保我的新方法返回与旧方法相同的结果。

这里就是我结束了:

public static void CompareExecutions<TObject, TParameter, TReturn>(this TObject originalSource, TObject alternateSource, IEnumerable<TParameter> parameters, Func<TObject, TParameter, TReturn> testExpression) 
    where TObject : class 
    where TReturn : class 
{ 
    var originalResults = new List<TReturn>(); 
    using (new Profile("Original Source")) 
     foreach (var parameterSet in parameters) 
      originalResults.Add(testExpression(originalSource, parameterSet)); 

    var alternateResults = new List<TReturn>(); 
    using (new Profile("Alternate Source")) 
     foreach (var parameterSet in parameters) 
      alternateResults.Add(testExpression(alternateSource, parameterSet)); 

    var comparer = new PropertyComparer<TReturn>(); 
    int errorCount = 0; 
    for (int i = 0; i < parameters.Count(); i++) 
    { 
     if (!comparer.Equals(originalResults[i], alternateResults[i])) 
     { 
      errorCount++; 
      Debug.WriteLine("^--- Mismatch for parameter {0}:\r\n\t{1}", i, string.Join("\r\n\t", parameters.ElementAt(i))); 
     } 
    } 

    if (errorCount > 0) 
     Assert.Fail("The results did not match for {0} items", errorCount); 
} 

我用这样的:

public class OriginalClass 
{ 
    public virtual ResultClass MyMethod(string argOne, int argTwo) 
    {/*...*/} 
} 

public class DerivedClass: OriginalClass 
{ 
    public override ResultClass MyMethod(string argOne, int argTwo) 
    {/*New implementation of the original code...*/} 
} 
//[...] 
public void TestTheseTwoClasses() { 
    var original = new OriginalClass(); 
    var derivedClass = new DerivedClass(); 

    original.CompareExecutions(
     derivedClass, 
     new[] { 
      new {One = "First", Two=1}, 
      new {One = "Second", Two=2}, 
      new {One = "Third", Two=3} 
     }, 
     (c,p) => c.MyMethod(p.One, p.Two) 
    ); 
} 
相关问题