Есть ли способ вставить процесс создания экземпляров autofac?
У меня есть три класса объявлений, как указано выше
[Plug("hello")]
public class Plug1 : IPlug{}
[Plug("hello")]
public class Plug2 : IPlug{}
[Plug("world")]
public class Plug3 : IPlug{}
Когда я использую container.Resolve<IEnumerable<IPlug>>()
чтобы решить, я получаю все экземпляры, которые реализуют IPlug
Интерфейс, однако, я хочу получить первое и второе (или по миру, который экземпляр был помечен атрибутом Plug("hello")
).
Есть ли способ добиться этого?
Я хотел бы избежать использования
container.Resolve<IEnumerable<IPlug>>()
.Where(t => t.FirstAttribute<Plug>() != null
&& t.FirstAttribute<Plug>().Id == "Hello")
Я всегда чувствую, что это не лучшая практика в результате выступления.
1 ответ
Есть много способов сделать то, что вы хотите.
Самый простой способ - зарегистрировать ваш тип как именованную регистрацию.
builder.RegisterType<Plug1>().As<IPlug>().WithMetadata("plug", "hello");
builder.RegisterType<Plug2>().As<IPlug>().WithMetadata("plug", "hello");
builder.RegisterType<Plug3>().As<IPlug>().WithMetadata("plug", "world");
Вы также можете использовать атрибут для регистрации этих типов:
builder.RegisterType<Plug1>()
.As<IPlug>()
.WithMetadata("plug", typeof(Plug1).FirstAttribute<Plug>().?Id ?? "Default");
Тогда вы сможете получить все имена IPlug
регистрация с использованием IEnumerable<Meta<IPlug>>
:
container.Resolve<IEnumerable<Meta<IPlug>>>()
.Where(m => m.Metadata["plug"] as String == "hello")
.Select(m => m.Value);
Если вы не хотите фильтровать во время выполнения, но во время компоновки корня IoC и IEnumerable<IPlug>
всегда разрешит отфильтрованный IEnumerable<IPlug>
тогда вы можете переопределить IEnumerable<IPlug>
постановка на учет:
builder.Register(c => c.Resolve<IEnumerable<Meta<IPlug>>>()
.Where(m => m.Metadata["plug"] as String == "hello")
.Select(m => m.Value))
.As<IEnumerable<IPlug>>();