C# Unity:更改隐式注册的默认生存期管理器和/或禁用它们
Unity容器将自动解析它自己可以识别的任何类型,而无需手动注册。这在某些方面是好的,但我的问题是它使用了一个C# Unity:更改隐式注册的默认生存期管理器和/或禁用它们,c#,.net,dependency-injection,unity-container,C#,.net,Dependency Injection,Unity Container,Unity容器将自动解析它自己可以识别的任何类型,而无需手动注册。这在某些方面是好的,但我的问题是它使用了一个TransientLifetimeManager来进行这种类型的解析,而我几乎总是想要一个containerControlled LifetimeManager。当然,我仍然可以手动将我的类型注册为Singleton,但是如果我忘记了,在启动时不会得到未处理的异常,应用程序将成功启动,一切都将正常工作。但是最终会有一些bug,可能非常微妙,很难诊断,因为一个类型有多个实例是单例的 所以我
TransientLifetimeManager
来进行这种类型的解析,而我几乎总是想要一个containerControlled LifetimeManager
。当然,我仍然可以手动将我的类型注册为Singleton,但是如果我忘记了,在启动时不会得到未处理的异常,应用程序将成功启动,一切都将正常工作。但是最终会有一些bug,可能非常微妙,很难诊断,因为一个类型有多个实例是单例的
所以我的问题是:有没有一种方法可以指定不同的默认生存期管理器,或者完全禁用默认的自动解析行为,并将容器限制为我自己注册的类型(直接或按照我自己的约定)
有没有一种方法可以指定不同的默认生存期管理器
是的,您可以使用将使用不同生存期管理器的容器扩展。有关示例,请参见
或者完全禁用默认的自动解析行为,并将容器限制为我自己注册的类型
是的,容器扩展也可以做到这一点
首先在显式注册期间记录注册的BuildKey。然后在创建对象之前检查BuildKey是否已显式注册
public class RegistrationTrackingExtension : UnityContainerExtension
{
private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations =
new ConcurrentDictionary<NamedTypeBuildKey, bool>();
protected override void Initialize()
{
base.Context.Registering += Context_Registering;
base.Context.Strategies.Add(
new ValidateRegistrationStrategy(this.registrations), UnityBuildStage.PreCreation);
}
private void Context_Registering(object sender, RegisterEventArgs e)
{
var buildKey = new NamedTypeBuildKey(e.TypeTo, e.Name);
this.registrations.AddOrUpdate(buildKey, true, (key, oldValue) => true);
}
public class ValidateRegistrationStrategy : BuilderStrategy
{
private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations;
public ValidateRegistrationStrategy(ConcurrentDictionary<NamedTypeBuildKey, bool> registrations)
{
this.registrations = registrations;
}
public override void PreBuildUp(IBuilderContext context)
{
if (!this.registrations.ContainsKey(context.BuildKey))
{
Exception e = new Exception("Type was not explicitly registered in the container.");
throw new ResolutionFailedException(context.BuildKey.Type, context.BuildKey.Name, e, context);
}
}
}
}
公共类注册跟踪扩展:UnityContainerExtension
{
私有ConcurrentDictionary注册=
新的ConcurrentDictionary();
受保护的覆盖无效初始化()
{
base.Context.registing+=Context\u registing;
base.Context.Strategies.Add(
新的ValidateRegistrationStrategy(this.registrations),UnityBuildStage.PreCreation);
}
私有无效上下文\u注册(对象发送方、注册方目标)
{
var buildKey=new NamedTypeBuildKey(e.TypeTo,e.Name);
this.registrations.AddOrUpdate(buildKey,true,(key,oldValue)=>true);
}
公共类验证注册策略:BuilderStrategy
{
私人词典注册;
公共验证注册策略(ConcurrentDictionary注册)
{
这个。注册=注册;
}
公共覆盖无效预构建(IBuilderContext上下文)
{
if(!this.registrations.ContainsKey(context.BuildKey))
{
异常e=新异常(“类型未在容器中显式注册”);
抛出新的ResolutionFailedException(context.BuildKey.Type,context.BuildKey.Name,e,context);
}
}
}
}
然后添加扩展,注册一些类并解析。如果未显式注册该类,则将引发异常
IUnityContainer container = new UnityContainer();
// Add container extension
container.AddNewExtension<RegistrationTrackingExtension>();
// Register types
container.RegisterType<MyClass>();
container.RegisterType<IMyClass, MyClass>();
container.RegisterType<IMyClass, MyClass>("A");
// These succeed because they were explicitly registered
container.Resolve<IMyClass>();
container.Resolve<IMyClass>("A");
container.Resolve<MyClass>();
// MyClass2 was not registered so this will throw an exception
container.Resolve<MyClass2>();
IUnityContainer container=newunitycontainer();
//添加容器扩展名
container.AddNewExtension();
//寄存器类型
container.RegisterType();
container.RegisterType();
容器注册类型(“A”);
//这些成功是因为它们已显式注册
container.Resolve();
集装箱。决议(“A”);
container.Resolve();
//MyClass2未注册,因此将引发异常
container.Resolve();
我尝试了DefaultLifetimeManegerExtension,但不知何故它不起作用。(也许团结已经改变了?)。无论如何,如果您不想使用扩展,也可以使用RegsiterByConvention功能
container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.None, WithName.Default, x => new DisposingTransientLifetimeManager());
这将使用“DisposingTransientLifetimeManager”注册所有类,我选择将其用作默认类。请注意,您应该在注册开始时执行此操作,因为所有注册都将覆盖以前任何相同类型和名称的注册。可能重复的Great;这似乎给了我一种设置默认
LifetimeManager
的方法。我还想知道是否有办法禁用自动/隐式注册;这两种解决方案都非常有效。而且,RegistrationTrackingExtension
已经在应用程序中发现了几个错误!