1

What I want to do is to execute a method on one of various objects, but before and after the method call, I need to execute functions to do various maintenance tasks. The functions to run before and after are always the same. The method's return type and parameters can be almost anything.

Currently, I'm doing this by defining delegates for every possible method signature that I'm using, and it's getting stupendously awkward to do. This is one example:

protected delegate void DelVoidString(string string1);
protected void Execute(DelVoidString p, string string1)
{
    PreInvoke();
    p.Invoke(string1);
    PostInvoke();
}

Other than the signatures, the code on all of them is identical. So my question is: is there a better way of doing this? I'm not attached to using delegates, just as long as I have some means of executing PreInvoke() and PostInvoke() before and after those method calls that need them, without having to remember to write out that code every single time.

I have only a vague knowledge of Lambda expressions...can they help me out better here? Or am I missing something else stupendously obvious? Thanks!

4

3 回答 3

4

您可以使用泛型和内置System.Action委托类型来减少一些重复:

protected void Execute(Action action)
{
    PreInvoke();
    action();
    PostInvoke();
}

protected void Execute<T>(Action<T> action, T arg)
{
    PreInvoke();
    action(arg);
    PostInvoke();
}

protected void Execute<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
    PreInvoke();
    action(arg1, arg2);
    PostInvoke();
}

// Additional methods for three arguments, four arguments, etc.

要处理返回值,请使用System.Func

protected TResult Execute<TResult>(Func<TResult> func)
{
    PreInvoke();
    TResult result = func();
    PostInvoke();
    return result;
}

protected TResult Execute<T, TResult>(Func<T, TResult> func, T arg)
{
    PreInvoke();
    TResult result = func(arg);
    PostInvoke();
    return result;
}

您可能还想研究 C# 的面向方面编程 (AOP)。

于 2012-04-26T03:58:49.630 回答
0

如果您需要这种用于很多方法的前/后调用机制,我认为您应该考虑使用适用于 .net 的AOP工具,例如PostSharp

您可以在Dror Helper 博客或 PostSharp 站点中的示例下查看使用 PostSharp 的OnMethodBoundaryAspect的示例

于 2012-04-26T05:25:19.143 回答
0

提供其他人提供的主题的变体 - 您可以考虑创建一个通用抽象基类并从它继承,如下所示:

public abstract class Executable<T>
{
    protected void Execute(Action<T> action, T value)
    {
        PreInvoke();
        action();
        PostInvoke();
    }
    private void PreInvoke() { /* something */ }
    private void PostInvoke() { /* something */ }
}

public MyFooExecutable : Executable<string>
{
}

这种实现将泛型类型关闭到string类上MyFooExecutable。这将允许您拥有改变类型的其他子类,而不会为所有类型的 T 保留类型。根据您的 Pre/Post-Invoke 方法所做的事情,您甚至可以将它们放入扩展方法并编码到接口中:

public interface IInvocable
{
   void PreInvoke();
   void PostInvoke();
}

public class MyFooExecutable : IInvocable
{
    public void PreInvoke() { /* something */ }
    public void PostInvoke() { /* something */ }
}

public static class InvocableExtensions
{
    public static void Execute<T>(this IInvocable self, Action<T> action, T value)
    {
        self.PreInvoke();
        action(value);
        self.PostInvoke();
    }
}
于 2012-04-26T04:24:32.573 回答