Разрешите все классы, помеченные атрибутом как IEnumerable <Type>, используя Autofac - PullRequest
0 голосов
/ 11 марта 2020

У меня есть 3 класса, помеченных атрибутом


[MyAttribute("xyz")]
class Class1
{}
//... other classes annotated with MyAttribute

Я зарегистрировал все типы

IContainer container ;
var builder = new ContainerBuilder();

//register all types annotated by MyAttribute
Assembly assembly = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly)
    .Where(t => t.GetCustomAttribute<MyAttribute>() != null);

//other registered classes /services

container = builder.Build();

Попробуйте разрешить:

//what this line(s) can be for only class that annotated by attribute
IEnumerable<Type> types =  container.Resolve<IEnumerable<Type>>(); 

Этот ответ не помогло

Как решить и получить IEnumerable<Type>

1 Ответ

1 голос
/ 11 марта 2020

Когда вы делаете это:

builder.RegisterAssemblyTypes(assembly)
    .Where(t => t.GetCustomAttribute<MyAttribute>() != null);

Под прикрытием это в основном делает это:

var types = assembly.GetTypes().Where(t => t.GetCustomAttribute<MyAttribute>() != null)
foreach(var type in types)
{
  builder.RegisterType(type).AsSelf();
}

Допустим, у вас было три типа с атрибутом: MyClass1, MyClass2, MyClass3. Это означает, что регистрация в основном будет такой же, как:

builder.RegisterType<MyClass1>();
builder.RegisterType<MyClass2>();
builder.RegisterType<MyClass3>();

Ни при каких обстоятельствах вы не регистрируете тип Type с помощью Autofa c.

Честно, я бы рекомендовал не регистрировать супер базовые c базовые типы, такие как string или Type с Autofa c в любом случае. Я бы создал фабрику, которая получает информацию. Таким образом, если мне когда-нибудь понадобится два разных списка Type, я могу легко разделить их, используя два разных заводских интерфейса.

Но, допустим, вы все равно хотите это сделать, вам действительно нужно зарегистрироваться Type не MyClass1 или что-то еще. Autofa c не делает ничего подобного из коробки. Вы должны будете сделать это сами.

У меня нет этого запуска через компилятор, но это должно быть что-то вроде ...

var types = assembly.GetTypes().Where(t => t.GetCustomAttribute<MyAttribute>() != null)
foreach(var type in types)
{
  builder.RegisterInstance(type).As<Type>();
}

Идея в том, что вы хотите Type зарегистрировано, чтобы вы могли перечислять эти вещи, а не то, что вы пытаетесь создать экземпляр того, что вы нашли Вы не хотите RegisterType(type), потому что это означает, что в основном вы хотите, чтобы Autofa c мог создавать экземпляр из type, а не отслеживать список этих типов так что вы можете получить их позже . Такая путаница - еще одна веская причина оставить это за фабрикой вашего собственного творения.

Действительно просто:

public class TypeFactory
{
  public IEnumerable<Type> Types {get;}
  public TypeFactory(IEnumerable<Type> types)
  {
     this.Types = types;
  }
}

Тогда:

var types = assembly.GetTypes().Where(t => t.GetCustomAttribute<MyAttribute>() != null)
var factory = new TypeFactory(types);
builder.RegisterInstance(factory);

Затем решите TypeFactory вместо того, чтобы пытаться разрешить напрямую IEnumerable<Type>.

...