Как избежать соединения с контейнером IoC

112
9

Я занимаюсь разработкой расширяемой структуры с использованием DI и IoC. Пользователи должны иметь возможность переопределять существующие функции внутри фреймворка, отбросив их собственные реализации в контейнер.


Как я могу разрешить пользователям делать это, не требуя от них знать, какой контейнер IoC я использую?


Мое текущее решение на полпути - структурировать мои сборки следующим образом:


1) Определите абстрактные сборки, содержащие только интерфейсы.


2) Определите конкретные сборки, которые реализуют эти интерфейсы. Пользователи могут определять свои собственные, чтобы переопределить существующие функции.


3) Определите привязки контейнера в отдельных сборках; то есть одной связывающей сборки на конкретный узел.


Это означает, что конкретные сборки не связаны с конкретным контейнером IoC, и они будут закрыты против изменения, если я использую другой контейнер. Тем не менее, пользователям по-прежнему необходимо знать, какой контейнер использует моя инфраструктура для записи сборочных сборок, и им нужно будет освободить новые сборки связывания, если я изменил контейнер IoC (т.е. От Ninject до Spring).


Я что-то пропустил?

спросил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
1
Решение
133

Записать свободно связанный код. Приложения должны зависеть от контейнеров. Рамки не должны.

ответил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
74

Общий подход заключается в абстрактном контейнере с общим локатором сервиса


Автор MvcExtensions довольно успешно отделил IoC.

ответил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
61

Common Service Locator - это один подход, но он содержит только методы для решения, а не для регистрации.


Вы можете посмотреть, как это реализовано в проекте agatha-rrsl. Здесь более полное описание здесь, но вкратце:

    определить интерфейс-агностик для регистрации и разрешения типов
    предоставляют реализации для разных контейнеров (или позволяют пользователям представлять реализации)

Предостережение: вы, вероятно, не сможете напрямую использовать свой контейнер в своей библиотеке.

ответил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
44

Я решил это с помощью атрибута и предоставить класс сканера, который используется для поиска всех реализаций и интерфейсов, которые они предоставляют.


public class ComponentAttribute : Attribute
{}

// class that should be registered in the container.
[Component]
public class MyService : IMyService
{}

// Contains information for each class that should be
// registered in the container.
public interface IContainerMapping
{
public Type ImplementationType {get;}
public IEnumerable<T> ImplementedServices {get; }
}

public class ComponentProvider
{
public static IEnumerable<IContainerMapping> Find()
{
var componentType = typeof(ComponentAttribute);
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
if (type.GetCustomAttributes(componentType, false).Count == 0)
continue;

var mapping = new ContainerMapping(type);
List<Type> interfaces new List<Type>();
foreach (var interfac in type.GetInterfaces())
{
//only get our own interfaces.
if (interface.Assembly != Assembly.GetExecutingAssembly())
continue;

interfaces.Add(interfac);
}

mapping.ImplementedServices = interfaces;
yield return mapping;
}
}
}


Это решение дает пользователю большую гибкость. Он может предоставить собственное решение, используя атрибут [Component] напрямую или используя ваше решение.


То, что пользователь должен делать, это что-то вроде:


foreach (var mapping in ComponentProvider.Find())
myContainer.Register(mapping.ImplementationType).As(mapping.ImplementedServices);

Я обычно создаю готовое решение, предоставляя проект MyProject.autofac, который регистрирует все в моем любимом контейнере.

ответил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
43

Два простых варианта: либо предоставить вашему пользователю какой-либо словарь, где они могут регистрировать сопоставления типов, либо альтернативно просто предоставить им интерфейс контейнера, который предоставляет все службы, которые, по вашему мнению, вы, вероятно, потребуете, и разрешите пользователям поставлять свои собственные упакованные контейнеры. Извиняюсь, если они не соответствуют вашему сценарию, я в первую очередь использую Unity, поэтому я не знаю, действительно ли Ninject и т.д. Придумывают, что Unity не делает.

ответил(а) 2021-01-27T23:52:44+03:00 4 недели, 1 день назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема