C#代表具有灵活的签名

时间:2012-04-26 03:51:23

标签: c# delegates

我想要做的是在各种对象之一上执行一个方法,但在方法调用之前和之后,我需要执行函数来执行各种维护任务。之前和之后运行的功能始终相同。方法的返回类型和参数几乎可以是任何东西。

目前,我正在通过为我正在使用的每个可能的方法签名定义委托来实现这一点,并且它正在变得非常难以做到。这是一个例子:

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

除了签名之外,所有签名上的代码都是相同的。所以我的问题是:有更好的方法吗?我并不依赖于使用委托,只要我有一些在需要它们的方法调用之前和之后执行PreInvoke()和PostInvoke()的方法,而不必记住每次都写出该代码。 / p>

我对Lambda表达式只有一个模糊的知识......他们能在这里帮助我更好吗?或者我错过了一些非常明显的东西?谢谢!

3 个答案:

答案 0 :(得分: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)。

答案 1 :(得分: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();
    }
}

答案 2 :(得分:0)

如果您需要针对很多方法使用此前/后调用机制,我认为您应该考虑使用AOP工具来处理。PostSharp

您可以在Dror Helper blogExamples下的PostSharp网站中看到使用PostSharp的 OnMethodBoundaryAspect 的例子