简体   繁体   English

我可以创建一个实用的方法,它将任意表达式作为参数并调用它吗?

[英]Can I make a utility method which takes an arbitrary expression as a parameter and calls it?

The exact reasons I might want to do this are a bit hard to go into without posting loads of code, but here's an example of one scenario: 我可能想要这样做的确切原因有点难以在没有发布大量代码的情况下进行,但这是一个场景的示例:

try
{
    x.Method(123,"test");
    Assert.Fail("No exception thrown");
}
catch (ApplicationException e)
{
    StringAssert.StartsWith(e.Message, "Oh no!");
}

I'd like to refactor this to something like... (pseudo-code) 我想重构一下像......(伪代码)

TestExceptionMessage({x.Method(123,"test")},"Oh no!");

void TestExceptionMessage(func,string message)
{
    try
    {
        func();
        Assert.Fail("No exception thrown");
    }
    catch (ApplicationException e)
    {
        StringAssert.StartsWith(e.Message, message);
    }
}

I know C# is pretty flexible with lambdas and so on, but is this pushing it too far or is it reasonable straightforward? 我知道C#对lambdas等非常灵活,但这是推动它太远还是合理的直接?

Yes, and it's pretty straight forward. 是的,而且非常直接。 You can pass a Action delegate (or really any delegate type) into a method and call it: 您可以将Action委托(或任何委托类型)传递给方法并调用它:

void TestExceptionMessage(Action action, string message)
{
    try
    {
        action();
        Assert.Fail("No exception thrown");
    }
    catch (ApplicationException e)
    {
        StringAssert.StartsWith(e.Message, message);
    }
} 

That delegate can be a reference to a method or it could be a lambda expression like this: 该委托可以是对方法的引用,也可以是这样的lambda表达式:

var x = new MyClass();
TestExceptionMessage(() => x.Method(123, "test"),"Oh no!");

However, if you really want to know the expression being used (eg if you want to be able to tell what method is being called) you need to use an Expression<Action> 但是,如果您真的想知道正在使用的表达式 (例如,如果您希望能够告诉正在调用的方法),则需要使用Expression<Action>

void TestExceptionMessage(Expression<Action> expression, string message)
{
    try
    {
        var methodName = (expression.Body as MethodCallExpression)?.Method.Name;
        if (methodName != null) 
        { 
            Debug.WriteLine($"Calling {methodName}");
        }
        expression.Compile().Invoke();
        Assert.Fail("No exception thrown");
    }
    catch (ApplicationException e)
    {
        StringAssert.StartsWith(e.Message, message);
    }
} 

And thanks to a little compiler magic, you can call with the same lambda syntax: 感谢一点点编译魔术,你可以使用相同的lambda语法调用:

var x = new MyClass();
TestExceptionMessage(() => x.Method(123, "test"),"Oh no!");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以动态创建一个表示 lambda 的表达式,该表达式在输入参数上调用一个方法吗? - Can I dynamically create an expression representing a lambda which calls a method on the input parameter? 如何制作一个遍历列表并以要访问的数据成员作为输入参数的函数 - How can I make a function that loops over a list and takes which data member to access as input parameter 自己添加字典的方法 <TKey,TValue> 这需要表达 <Func<T> &gt;作为参数 - Own Add Method for Dictionary<TKey,TValue> which takes Expression<Func<T>> as parameter 如何使用打开/关闭开关重复调用异步方法 - How can I make repeated calls to an async method with an on/off switch Linq表达式返回第一个带有1个字符串参数的重载方法 - Linq expression to return the first overloaded method that takes 1 string parameter 如何对以Lambda表达式为参数的存储库方法进行单元测试 - How to Unit Test Repository Method That Takes Lambda Expression as A Parameter 如何为具有其他方法的参数的方法创建线程 - How can I make thread for a method with parameter from another method 无法对调用静态方法的方法进行单元测试,如何重新设计该程序? - Can't unit test a method which calls a static method, how can I re-design this program? 如何创建一个采用映射的通用列表和字符串参数的方法? - How to create a method which takes generic list and string parameter with mapping? 如何制作一个正确调用使用泛型的动作的表单? - How can I make a form which properly calls an action which uses generics?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM