Подтвердить что ты не робот

Каковы различные методы инъекции сквозных проблем?

Каковы различные методы для инъекции сквозных проблем в класс, чтобы я мог минимизировать сцепление участвующих классов, сохраняя проверяемый код (TDD или иначе)?

Например, рассмотрим, есть ли у меня класс, который требует как функций ведения журнала, так и централизованного управления исключениями. Должен ли я использовать DIP и вводить обе требуемые проблемы через интерфейс в класс, который их требует? Должен ли я использовать локатор службы, который я передаю каждому классу, для чего потребуются некоторые функции сквозной резки? Есть ли другое решение? Я задаю неправильный вопрос?

4b9b3361

Ответ 1

Конструктивный шаблон Decorator является отличной отправной точкой для реализации сквозных проблем.

Сначала вам нужно определить интерфейс, который моделирует рассматриваемую службу. Затем вы реализуете реальную функциональность этой службы, не задумываясь о своей сквозной заботе.

Затем вы можете впоследствии внедрить классы украшений, которые обертываются вокруг других экземпляров и реализуют требуемую сквозную проблему.

Этот подход может быть реализован целиком с помощью обычных объектов С# (POCOs) и не требует дополнительных фреймворков.

Однако, если вам надоело писать все дополнительные декораторы, вы можете использовать фреймворк. У меня нет опыта работы с явными структурами AOP, но большинство контейнеров DI, таких как Castle Windsor, предлагают AOP-подобные функции.


Вот пример использования Decorators. Скажем, у вас есть следующий интерфейс:

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

Ваша конкретная реализация может сделать что-то очень интересное, например, написать строку в консоли:

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

Если вы хотите зарегистрировать операцию DoStuff, теперь вы можете выполнить регистрацию 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);
    }
}

Вы можете продолжать писать новые Декораторы, например, кеширующий Декоратор или тот, который реализует безопасность и т.д., и просто обертывать их друг вокруг друга.

Примечание. Я редко рекомендую статические интерфейсы, поэтому интерфейс Log.Write не является рекомендацией, а просто означает как заполнитель. В реальной реализации я бы ввел какой-то интерфейс ILogger в LoggingThing.

Ответ 2

Вы можете использовать шаблон 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, поэтому, пожалуйста, простите любые синтаксические ошибки.