What are the different methods for injecting cross-cutting concerns?

前端 未结 2 1539
被撕碎了的回忆
被撕碎了的回忆 2020-12-08 01:01

What are the different methods for injecting cross-cutting concerns into a class so that I can minimize the coupling of the classes involved while keeping the code testable

相关标签:
2条回答
  • 2020-12-08 01:44

    You can use the Observer pattern.

    The Subject holds a collection of Observers. When the Subject performs an action, it notifies the Observers of the change. The Observers can then perform an action without the Subject caring what that action is.

    Here's an example:

    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.");
        }
    }
    

    I'm used to Java, so please forgive any syntax errors.

    0 讨论(0)
  • 2020-12-08 01:49

    The Decorator design pattern is an excellent starting point for implementing cross-cutting concerns.

    First you need to define an interface that models the service in question. Then you implement the real functionality of that service without thinking about your cross-cutting concern at all.

    Then you can subsequently implement decorating classes that wrap around other instances and implement the desired cross-cutting concern.

    This approach can be implemented entirely with Plain Old C# Objects (POCOs) and requires no extra frameworks.

    However, if you get tired of writing all the extra decorators, you may want to use a framework. I have no experience with explicit AOP frameworks, but most DI Containers such as Castle Windsor offer AOP-like features.


    Here's an example of using Decorators. Let's say that you have the following interface:

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

    Your concrete implementation may do something very interesting, such as writing the string to the Console:

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

    If you wish to log the DoStuff operation, you can now implement a logging Decorator:

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

    You can keep writing new Decorators, like a caching Decorator or one that implements security and so on, and just wrap them around each other.

    Note: I rarely recommend static interfaces, so the Log.Write interface is not a recommendation, but merely mean as a placeholder. In a real implemetation, I'd inject some kind of ILogger interface into LoggingThing.

    0 讨论(0)
提交回复
热议问题