【问题标题】:Can a MemberExpression return a MethodMemberExpression 可以返回一个方法吗
【发布时间】:2014-07-08 17:53:52
【问题描述】:

我想用 C# 中的某种 Lambda 表达式返回一个方法(或方法信息)。

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”转换为非委托类型 '目的'。您是否打算调用该方法?

这在 c# 中是否可行,还是我应该放弃并传递带有方法名称的字符串并使用反射而不是使用 MemberExpression 进行查找?

【问题讨论】:

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

标签: c# reflection lambda func


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2011-09-27
    • 2016-05-13
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    相关资源
    最近更新 更多