简体   繁体   English

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

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

I have 3 classes annotated with Attribute我有 3 个用 Attribute 注释的类


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

I registered all types我注册了所有类型

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

Try to resolve:尝试解决:

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

This answer didn't help这个答案没有帮助

How to resolve and get IEnumerable<Type>如何解决和获取IEnumerable<Type>

When you do this:当你这样做时:

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

Under the covers it's basically doing this:在幕后,它基本上是这样做的:

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

Let's say you had three types with the attribute: MyClass1 , MyClass2 , MyClass3 .假设您有三种类型的属性: MyClass1MyClass2MyClass3 That means the registration would basically be the same as:这意味着注册基本上与:

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

At no point in there are you registering the type Type with Autofac.在任何时候,您都不会向 Autofac 注册类型Type

Honestly, I'd recommend against registering super generic base types like string or Type with Autofac anyway.老实说,我建议不要使用 Autofac 注册超级通用的基本类型,例如stringType I'd create a factory that gets the information.我会创建一个获取信息的工厂。 That way if I ever need to have two different lists of Type then I could separate them easily by using two different factory interfaces.这样,如果我需要有两个不同的Type列表,那么我可以通过使用两个不同的工厂接口轻松地将它们分开。

But let's say you want to do that anyway, you actually have to register Type not MyClass1 or whatever.但是假设您无论如何都想这样做,您实际上必须注册Type而不是MyClass1或其他什么。 Autofac doesn't do that sort of thing out of the box. Autofac 不会开箱即用。 You will have to do it yourself.你必须自己做。

I don't have this running through a compiler, but it should be something like...我没有通过编译器运行它,但它应该是这样的......

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

The idea is that you want the Type registered so you can list those things, not that you're trying to instantiate the things you located.这个想法是你想要注册Type以便你可以列出这些东西,而不是你试图实例化你找到的东西。 You don't want to RegisterType(type) because that means, basically, that you want Autofac to be able to create an instance of type , not track the list of those types so you can get them later .您不想RegisterType(type)因为这基本上意味着您希望 Autofac 能够创建type的实例,而不是跟踪这些类型的列表,以便您以后可以获取它们 This sort of confusion is another great reason to put this behind a factory of your own creation.这种混乱是将其置于您自己创建的工厂背后的另一个重要原因。

Really simply:真的很简单:

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

Then:然后:

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

Then resolve TypeFactory instead of trying to resolve directly an IEnumerable<Type> .然后解析TypeFactory而不是尝试直接解析IEnumerable<Type>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM