使用 Autofac 解析所有用 Attribute 注释为 IEnumerable<Type> 的 类

Resolve all classes that annotated with Attribute as IEnumerable<Type> using Autofac

我有 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>>(); 

这个answer没有帮助

如何解析得到IEnumerable<Type>

当你这样做时:

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();
}

假设您有三种类型的属性:MyClass1MyClass2MyClass3。这意味着注册 基本上 与:

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

您在任何时候都没有在 Autofac 中注册类型 Type

老实说,无论如何,我建议不要使用 Autofac 注册超级泛型基类型,如 stringType。我会创建一个获取信息的工厂。这样,如果我需要有两个不同的 Type 列表,那么我可以通过使用两个不同的工厂接口轻松地将它们分开。

但是假设您无论如何都想这样做,实际上您必须注册 Type 而不是 MyClass1 或其他任何内容。 Autofac 不会开箱即用。你将不得不自己做。

我没有通过编译器得到这个 运行,但它应该类似于...

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

想法是您希望 Type 注册以便您可以列出这些东西,而不是您试图实例化您找到的东西。您不想 RegisterType(type) 因为这基本上意味着您希望 Autofac 能够 创建 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>