Итак, я реализовал то, что, как мне кажется, называется инъекцией зависимостей (пожалуйста, поправьте меня, если я ошибаюсь!).Как структурировать инъекцию зависимостей в C#
У меня есть класс FooModel, который поддерживает состояние Foo. Здесь есть некоторые асинхронные методы, которые пытаются попробовать что-то. Обычно они работают, иногда они терпят неудачу на разных этапах. Я хотел бы, чтобы реализация FooModel и UpdateFoo() заставила абонентов реализовать их обработку того, что происходит в UpdateFoo(). Вот простой пример:
public class FooModel
{
private FooState fooState;
public async Task UpdateFooAsync(IHandler handler)
{
try
{
var newFooState = await Something();
fooState = newFooState;
handler.ItWorked();
}
catch
{
handler.ItDidntWork();
}
}
}
public interface IHandler
{
public void ItWorked();
public void ItDidntWork();
}
Теперь есть несколько других моделей, которые могут потребоваться для вызова UpdateFoo(). Например, рассмотрим BarModel:
public class BarModel
{
private BarState barState;
private FooModel foo;
public Bar()
{
this.foo = ModelProvider.Foo;
}
public void DoBar()
{
foo.UpdateFoo(new Handler(this));
}
private void Continue() {}
private void TryOtherThing() {}
public class Handler : IHandler
{
private BarModel bar;
public Handler(BarModel bar)
{
this.bar = bar;
}
public void ItWorked()
{
bar.Continue();
}
public void ItDidntWork()
{
bar.TryOtherThing();
}
}
}
Имейте в виду, что это простой пример. В UpdateFoo() может быть 2 - 6 "вилок". И может быть несколько разных классов, которые нужно вызвать UpdateFoo(). Я хочу заставить все эти вызывающие классы что-то делать на каждой из этих разных «вилок», поэтому я использовал интерфейс.
Однако, кажется невероятно громоздким, чтобы явно реализовать вложенный класс для каждого класса, который хочет вызвать UpdateFoo(). Тем более, что я должен передать родительский класс в качестве аргумента конструктору и т. Д. Идея вложенного класса вообще не сидит прямо со мной.
Является ли это хорошей идеей? Или это ужасно? Существуют ли более чистые рефакторинги? Я не могу сказать.
Edit: Изменены некоторые вещи в соответствии с рекомендациями Кай Brummund в
Что вы делают больше похоже на Command или Strategy-Pattern для меня. Я бы рекомендовал вам посмотреть на эти два. Инъекция зависимостей больше связана с зависимостями класса при времени построения/инициализации. Вызывающие методы не должны знать внутренние зависимости вашего класса. –
Другие подсказки OT: методы Async должны отражать это от их имени: UpdateFooAsync(), и вы никогда не должны использовать async void, если это возможно. Сделайте это async Task. –
Существует также точка, в которой ваш код явно разбивает инъекцию зависимостей: ваш BarModel имеет зависимость от Foo, но вы получаете его через ModelProvider в конструкторе. Если вы позволите передать в modelprovider или даже сам Foo в качестве аргументов, это будет инъекция зависимостей. –