注入横切关注点的不同方法有哪些?

时间:2009-11-10 15:53:46

标签: c# .net vb.net aop

将横切关注点注入类中的有哪些不同的方法,以便在保持代码可测试(TDD或其他)的同时最小化所涉及的类的耦合?

例如,考虑我是否有一个需要记录功能和集中式异常管理的类。我应该使用DIP并通过接口将所需的关注点注入需要它们的类中吗?我是否应该使用我传递给每个需要一些交叉功能的类的服务定位器?是否有完全不同的解决方案?我完全问错了问题吗?

2 个答案:

答案 0 :(得分:24)

Decorator设计模式是实施跨领域关注点的绝佳起点。

首先,您需要定义一个为相关服务建模的界面。然后,您可以实现该服务的真实功能,而无需考虑您的跨领域问题。

然后,您可以随后实现包装其他实例的装饰类,并实现所需的交叉关注。

这种方法可以完全用普通的旧C#对象(PO​​CO)实现,不需要额外的框架。

但是,如果你厌倦了编写所有额外的装饰器,你可能想要使用一个框架。我没有使用显式AOP框架的经验,但是大多数DI容器(例如Castle Windsor)提供了类似AOP的功能。


以下是使用装饰器的示例。假设您有以下界面:

public interface IMyInterface
{
    void DoStuff(string s);
}

您的具体实现可能会做一些非常有趣的事情,例如将字符串写入控制台:

public class ConsoleThing : IMyInterface
{
    public void DoStuff(string s)
    {
        Console.WriteLine(s);
    }
}

如果您希望记录DoStuff操作,现在可以实现一个日志记录器:

public class LoggingThing : IMyInterface
{
    private readonly IMyInterface innerThing;

    public LoggingThing(IMyInterface innerThing)
    {
        this.innerThing = innerThing;
    }

    public void DoStuff(string s)
    {
        this.innerThing.DoStuff(s);
        Log.Write("DoStuff", s);
    }
}

你可以继续编写新的装饰器,比如缓存装饰器或实现安全性的装饰器等,然后将它们包裹起来。

注意:我很少推荐静态接口,因此Log.Write接口不是推荐,而只是作为占位符。在真正的实现中,我会在LoggingThing中注入某种ILogger接口。

答案 1 :(得分:4)

您可以使用Observer模式。

主体拥有一组观察者。当主体执行操作时,它会通知观察者更改。然后,观察者可以在主体不关心该动作的情况下执行动作。

以下是一个例子:

public interface IThingObserver
{
    void Notify();  // can also pass in a parameter with event information
}

public class Thing
{
    private readonly ICollection<IThingObserver> observers;

    public Thing()
    {
        observers = new List<IThingObserver>();
    }

    public void RegisterObserver(IThingObserver observer)
    {
        observers.Add(observer);
    }

    public void UnregisterObserver(IThingObserver observer)
    {
        observers.Remove(observer);
    }

    private void NotifyObservers()
    {
        foreach (IThingObserver observer in observers)
        {
            observer.Notify();
        }
    }

    public void DoIt()
    {
        Console.WriteLine("Doing it...");
        NotifyObservers();
    }
}

public class LoggingThingObserver : IThingObserver
{
    public void Notify()
    {
        Log.Write("It is done.");
    }
}

我已经习惯了Java,所以请原谅任何语法错误。