如何使用Unity的名称动态注册generics类?

我有一个包含很多类(300+)和BaseClass的程序集,我希望注册一个带接口的generics类。

如果要解析接口的对象数组,则必须通过{ Name }注册。 我想自动在MainViewModel中有一个对象数组。

有没有办法用reflection自动化这个? 有什么建议?

示例(伪):

public class BaseClass { public void doFoo(); } public ClassNumber001 : BaseClass { } public ClassNumber002 : BaseClass { } public interface ISuperman { } public class Superman : ISuperman where T : BaseClass { } public MainViewModel(IEnumerable lotsofSuperman) { } 

手工实例:

 container.RegisterType<ISuperman, Superman >("ClassNumber001"); container.RegisterType<ISuperman, Superman >("ClassNumber002"); container.RegisterType<IEnumerable, ISuperman[]>(); 

这是我想到的可能对你有用的东西……

您可以按如下方式注册类型,并且应该适用于开放式generics 。

 container.RegisterType(typeof(ISuperman<>), typeof(Superman<>), ... ); 

注册通用参数和类型

希望这可以帮助!

是的,您需要使用reflection来轻松创建所需的所有映射。 由于您使用的是Unity 3,因此您可以利用“按惯例注册”在注册课程时提供帮助(更重的提升)。

我已经把你的伪代码翻译成真正的代码:

 public abstract class BaseClass { public abstract void DoFoo(); } public class ClassNumber001 : BaseClass { public override void DoFoo() { Console.WriteLine("001 Foo"); } } public class ClassNumber002 : BaseClass { public override void DoFoo() { Console.WriteLine("002 Foo"); } } public interface ISuperman { void Do(); } public class Superman : ISuperman where T : BaseClass { private T baseClass; public Superman(T baseClass) { this.baseClass = baseClass; } public void Do() { this.baseClass.DoFoo(); } } public class MainViewModel { public MainViewModel(IEnumerable lotsofSuperman) { foreach(ISuperman superman in lotsofSuperman) { superman.Do(); } } } 

然后按惯例使用注册来注册所有generics:

 IUnityContainer container = new UnityContainer(); container.RegisterTypes( AllClasses.FromAssembliesInBasePath().Where(t => typeof(BaseClass).IsAssignableFrom(t)) .Select(t => typeof(Superman<>).MakeGenericType(t)), t => new Type[] { typeof(ISuperman) }, t => t.GetGenericArguments().First().Name, WithLifetime.Transient); container.RegisterType, ISuperman[]>(); container.Resolve(); 

在上面的代码中,我们获得了从BaseClassinheritance的所有类,然后构造了一个类型Superman<>并使用BaseClass的名称将其映射到ISuperman 。 RegisterTypes调用相当于为每个BaseClass调用RegisterType:

 container.RegisterType("ClassNumber001"); container.RegisterType("ClassNumber002"); 

然后,当MainViewModel被解析时,它遍历所有ISuperman实例并调用打印出来的方法:

001 Foo
002 Foo

显示我们注入了2个ISuperman实例: SupermanSuperman

如果您需要BaseClasses的特定注册(例如非默认生命周期管理器),那么您可以按惯例使用注册来注册那些)。

有一些方法可以做到这一点。 一种是使用XML,其中定义了类型,例如MyClass和IMyClass,并且在运行时它根据可用的程序集解析。 但在我看来,更好的方法是创建一个项目,您可以委派加载依赖项的责任。

让我们说你创建一个这样的类:

  public class MyClass : IMyClass { private readonly IUnityContainer _container; #ctor // initialie the container through the constructor public void DoWork() where Class: Interface { _container.RegisterType( //TODO: You can setup the container lifecycle which can be transient // or singleton or custom based on your project requirement ) } } 

现在,无论谁需要注册自己,都可以调用此接口IMyClass来使自己在容器中注册,并且可以将依赖项注入到执行该任务的任何类中。