gpt4 book ai didi

.net - 为什么 Unity RegisterType 无法正确重新注册映射

转载 作者:行者123 更新时间:2023-12-02 15:10:43 27 4
gpt4 key购买 nike

我需要注册许多类型映射,但对于少数类型映射,我需要使用不同的依赖注入(inject)属性重新注册。

对于 Unity,这似乎是不可能的,并且这似乎是 RegisterType<TFrom, TTo>() 的一个错误。

这是一个单元测试,用于演示第二次调用不会清除之前的依赖关系图

[TestClass]
public class UnityContainerTests
{
[TestMethod]
public void UnityShouldCorrectlyResolveReRegisteredType()
{
var container = new UnityContainer();

container.RegisterType<IB, B>(new ContainerControlledLifetimeManager())
.RegisterType<IA, A>(new ContainerControlledLifetimeManager(), new InjectionProperty("B", new B()))

//now re-register mapping without property override, this should
//mean that A.B is resolved to our previously registered singleton but it doesnt
//comment out the line above and notice the test passes

.RegisterType<IA, A>(new ContainerControlledLifetimeManager());

var a = container.Resolve<IA>();
var b = container.Resolve<IB>();

Assert.AreEqual(a.B, b);
}
}

public class A : IA
{
[Dependency] public IB B { get; set; }
}

public interface IA
{
IB B { get; set; }
}

public class B : IB { }

public interface IB { }

有人知道任何解决方法吗?

更新 我在 Unity Codeplex 项目门户上提出了一个“问题”,如果您遇到过此问题,那么我建议您支持我的修复请求 https://unity.codeplex.com/workitem/12777

最佳答案

问题是,当 A 注册到 InjectionProperty 时,Unity 内部会创建一个策略来解决 B 依赖关系。该策略与 A 类型的构建 key 相关联,并且属于 SpecifiedPropertiesSelectorPolicy 类型(它实现 IPropertySelectorPolicy)。此策略存储 InjectionProperty 值(即 new B())。

A再次重新注册时,该策略不会从策略列表中删除,因此当IA(最终A)得到解决时Unity 查找与类型 A 的构建 key 关联的 IPropertySelectorPolicy 并使用该值注入(inject) A

一种解决方案是删除IPropertySelectorPolicy。删除后,当解析 A 时,Unity 将创建一个新的策略来解析 B 依赖项,这将返回向容器注册的现有单例。

有了这个,单元测试应该通过:

[TestMethod]
public void UnityShouldCorrectlyResolveReRegisteredType()
{
var container = new UnityContainer();

container.RegisterType<IB, B>(new ContainerControlledLifetimeManager())
.RegisterType<IA, A>(new ContainerControlledLifetimeManager(),
new InjectionProperty("B", new B()))


container.RegisterType<IA, A>(new ContainerControlledLifetimeManager(),
new ClearPropertySelectorPolicy());

var a = container.Resolve<IA>();
var b = container.Resolve<IB>();

Assert.AreEqual(a.B, b);
}

public class ClearPropertySelectorPolicy : InjectionMember
{
public override void AddPolicies(Type serviceType,
Type implementationType,
string name,
Microsoft.Practices.ObjectBuilder2.IPolicyList policies)
{
policies.Clear<IPropertySelectorPolicy>(
new NamedTypeBuildKey(implementationType, name));
}
}

但是如果没有注入(inject)属性(可能是构造函数中的依赖项)怎么办?在这种情况下,清除 IPropertySelectorPolicy 将不起作用;我们需要清除另一个策略(但要清除什么策略?)。我认为以下内容清除了构建 key 的所有策略:

public class ClearAllPolicies : InjectionMember
{
public override void AddPolicies(Type serviceType, Type implementationType, string name, IPolicyList policies)
{
var buildKey = new NamedTypeBuildKey(implementationType, name);

policies.Clear<IBuildKeyMappingPolicy>(buildKey);
policies.Clear<IConstructorSelectorPolicy>(buildKey);
policies.Clear<IBuildPlanCreatorPolicy>(buildKey);
policies.Clear<IBuildPlanPolicy>(buildKey);
policies.Clear<IMethodSelectorPolicy>(buildKey);
policies.Clear<IPropertySelectorPolicy>(buildKey);
policies.Clear<ILifetimeFactoryPolicy>(buildKey);
policies.Clear<ILifetimePolicy>(buildKey);
policies.Clear<IBuilderPolicy>(buildKey);

DependencyResolverTrackerPolicy.RemoveResolvers(policies, buildKey);
}
}

一些注意事项:

  • policies.Clear() 由于锁定而相当昂贵
  • 这是基于几分钟的分析,尚未经过测试(除了单元测试之外)——场景可能会变得相当复杂。
  • 并发注册和解析可能会导致问题,因此如果出现这种情况,您可能必须自行管理同步。

此外,我不会真正推荐这种方法作为通用(非测试)方法。根据场景的不同,可能还有其他可行的方法(例如命名注册、解析器覆盖、工厂等)。如果您“设置好后就忘记它”,Unity 往往会发挥最佳效果。也就是说,在应用程序启动时执行所有注册,然后在应用程序持续时间内解析对象而不修改注册。

关于.net - 为什么 Unity RegisterType<TFrom, TTo> 无法正确重新注册映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30618988/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com