【问题标题】:Repeated template in class methods类方法中的重复模板
【发布时间】:2019-12-10 22:32:09
【问题描述】:

假设我有这个课程:

Class Foo:
        method1(){}
        method2(){}
        method3(){}
...

假设我有一些我想在课堂上的几个方法中重复做的动作。每个操作将在方法发生之前和之后执行。有没有一种优雅的方式来实现它?我想到了唯一的方法:

private void Setup(Action action)
{
  //Do something before
  action
  //Do something after
}

private void method1(args)
{
   Setup(()=>method)
}

但这会让我在我想实现的每个函数中反复调用 Setup。

【问题讨论】:

  • 说明你想做什么。如果你想实现方面,有很多可用的技术和机制。例如,ASP.NET MVC 和 Core 通过请求管道中的中间件来实现。在较小的规模上,您可以使用函数式技术,例如柯里化或将一个 Func<> 包装在另一个内部,以创建在调用最内层函数之前执行任何操作的函数
  • 这类东西通常通过像 PostSharp 这样的 IL 重写器来处理,或者通过使用代理(Castle 和相关库)来处理。一些手动反射也适用于简单场景 (Type.GetMethods()),可能与 T4 代码生成相结合。
  • @panoskarajohn 多播代表做了一些非常具体且与 OP 要求的非常不同的事情。 OP 希望在调用前后运行自定义代码。多播委托做一些非常不同的事情 - 它在触发时调用多个委托
  • 对我来说,优雅在于简约。因此,请考虑您的要求(关注可扩展性/未来方向)。并通过 KISS 实现 DRY
  • @ne1410s 这就是创建 AOP 技术的原因。如果你想要一个记录的操作,为什么不创建一个在实际调用之前或之后记录的“包装器”呢?比到处散布日志调用要简单得多。时间、验证等方面也是如此。虽然没有单一的技术。

标签: c#


【解决方案1】:

我用 DispatchProxy 做了一个简单的例子 灵感:DispatchProxy

https://dotnetfiddle.net/GzDR9r

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

//https://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/
public class Program
{

    public static void Main()
    {
        var foo = new  Foo();
        var decoratedFoo = AspectDecorator<IFoo>.Create(foo);

        Console.WriteLine("\n\nClass:\n");
        foo.method1();
        foo.method2();
        foo.method3();

        Console.WriteLine("\n\nDecorated Class:\n");
        decoratedFoo.method1();
        decoratedFoo.method2();
        decoratedFoo.method3();


    }

}
public class Foo : IFoo{
        public void method1(){Console.WriteLine("> call method1");}
        public void method2(){Console.WriteLine("> call method2");}
        public void method3(){Console.WriteLine("> call method3");}
}
public interface IFoo{
    void method1();
    void method2();
    void method3(); 
}
public class AspectDecorator<T> : DispatchProxy 
{
    private T _impl;
    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        Console.WriteLine($"Before : {targetMethod.Name}");
        var obj =  _impl.GetType().GetMethod(targetMethod.Name).Invoke(_impl, args);
        Console.WriteLine($"After : {targetMethod.Name}");
        return obj;
    }
    public void SetTarget(T target)
    {
        this._impl = target;
    }
    public static T Create(T decorated)
    {
        object proxy = Create<T, AspectDecorator<T>>();
        ((AspectDecorator<T>) proxy)._impl=decorated;
        return (T)proxy;
    }


}

【讨论】:

    猜你喜欢
    • 2014-05-17
    • 2016-04-12
    • 1970-01-01
    • 2012-09-08
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    相关资源
    最近更新 更多