В целом, принцип замещения Лискова является очень полезным руководством при разработке компонентов и сервисов для IoC. Если две реализации службы не могут использоваться взаимозаменяемо во время выполнения, тогда служба слишком общая, чтобы иметь смысл. В этом сценарии я бы хотел использовать что-то вроде IListSerializer<T>
, если это вариант для вас.
Однако, если вы хотите использовать именованные службы, это легко и ненавязчиво настроить с помощью Autofac.
Сначала зарегистрируйте каждый сериализатор по имени:
builder.RegisterType<CheckBoxListSerializer>()
.Named<IListSerializer>("checkBoxSerializer");
builder.RegisterType<TreeViewListSerializer>()
.Named<IListSerializer>("treeViewSerializer");
Затем добавьте глобально доступный параметр, который использует имя параметра конструктора, чтобы выбрать правильную реализацию. Мы можем сделать это с помощью модуля:
class NamedParameterResolutionModule<TService> : Module
{
Parameter _attachedParameter = new ResolvedParameter(
(pi, c) => pi.ParameterType == typeof(TService),
(pi, c) => c.ResolveNamed<TService>(pi.Name));
protected override void AttachToComponentRegistration(
IComponentRegistry registry,
IComponentRegistration registration)
{
registration.Preparing += (s, e) => {
e.Parameters = new[] { _attachedParameter }.Contact(e.Parameters);
};
}
}
Зарегистрируйте модуль так:
builder.RegisterModule<NamedParameterResolutionModule<IListSerializer>>();
Компоненты получат сериализатор в зависимости от имени параметра конструктора:
class SomeComponent : ...
{
public SomeComponent(IListSerializer checkBoxSerializer) { ...
}