2012-04-26 88 views
1

我想要做的是对各种对象之一执行方法,但在方法调用之前和之后,我需要执行函数来执行各种维护任务。前后运行的函数总是相同的。该方法的返回类型和参数几乎可以是任何东西。具有灵活签名的C#代表

目前,我通过为我使用的每种可能的方法签名定义代表来做到这一点,而且这样做的确令人感到非常尴尬。这是一个例子:

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

除了签名之外,所有这些签名都是相同的。所以我的问题是:有没有更好的方法来做到这一点?只要我有一些在需要它们的方法调用之前和之后执行PreInvoke()和PostInvoke()的方法,而不必记住每一次写出代码,我都不会使用委托。

我对Lambda表达式只有一种模糊的认识......他们能帮我在这里更好吗?或者我错过了其他惊人的东西?谢谢!

回答

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)。

+0

一般动作
的一个实例肯定会有所减少的代码。我不知道它们可能是通用的。有一些情况下返回值不是无效的,但这些情况很少。 我发现后我发现的另一个:那么Delegate.DynamicInvoke呢?速度不是问题,那么这可能是一种可能性吗? – RobinHood70 2012-04-26 04:11:13

+0

我更新了我的答案来处理返回值。 Delegate.DynamicInvoke是一种可能性,但如果您传递了不正确的参数数目,编译器将无法警告您。 – 2012-04-26 04:15:56

+0

谢谢,我认为随着你的改变,这可能是最好的选择。 – RobinHood70 2012-04-26 04:22:04

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> 
{ 
} 

这种实施关闭通用类型stringMyFooExecutable类。这将允许你有其他的子类,改变类型,而不用为所有类型的T打开类型。根据您的前/后调用方法做什么,你甚至可能与投入到这些扩展方法,而不是编码到一个接口脱身:

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

,如果你需要大量的这种前/后调用机制方法,我认为你应该考虑使用AOP工具.net像PostSharp

你可以看到Dror Helper blog或PostSharp网站使用PostSharp的OnMethodBoundaryAspectExamples