我正在使用 Unity IoC 容器,我需要拦截对某个基本接口的 Resolve 的任何调用,并运行我自己的自定义代码来构造这些类型。
换句话说,在下面的示例代码中,当我调用container.Resolve<IFooN>()
,如果它没有具体实现类型的实例,它会调用MyFactoryFunction
构造一个,否则我希望它返回缓存的副本。
标准 Unity 容器无法构造这些对象(update:因为它们是 .NET 远程处理对象,因此具体类不存在于本地计算机上的任何程序集中),并且我不想预先创建它们并使用 RegisterInstance 存储它们。
interface IFoo : IBase { ... }
interface IFoo2 : IBase { ... }
...
container.Resolve<IFoo2>();
...
IBase MyFactoryFunction(Type t)
{
...
}
我假设我可以创建一个 Unity 扩展来执行此操作,但我想知道是否已经有一个可以借用的解决方案。
为了完整起见,我应该添加另一个在 Unity 2 下工作的答案,因为我的另一个答案不再有效。由于您需要制定自定义构建器策略,因此涉及的内容稍微多一些。感谢 Unity 项目的 ctavares 提供了很多帮助这个线程在实施过程中:
public class FactoryUnityExtension : UnityContainerExtension
{
private ICustomFactory factory;
private CustomFactoryBuildStrategy strategy;
public FactoryUnityExtension(ICustomFactory factory)
{
this.factory = factory;
}
protected override void Initialize()
{
this.strategy = new CustomFactoryBuildStrategy(factory, Context);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
Context.Policies.Set<ParentMarkerPolicy>(new ParentMarkerPolicy(Context.Lifetime), new NamedTypeBuildKey<ParentMarkerPolicy>());
}
}
public class ParentMarkerPolicy : IBuilderPolicy
{
private ILifetimeContainer lifetime;
public ParentMarkerPolicy(ILifetimeContainer lifetime)
{
this.lifetime = lifetime;
}
public void AddToLifetime(object o)
{
lifetime.Add(o);
}
}
public interface ICustomFactory
{
object Create(Type t);
bool CanCreate(Type t);
}
public class CustomFactoryBuildStrategy : BuilderStrategy
{
private ExtensionContext baseContext;
private ICustomFactory factory;
public CustomFactoryBuildStrategy(ICustomFactory factory, ExtensionContext baseContext)
{
this.factory = factory;
this.baseContext = baseContext;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = (NamedTypeBuildKey)context.OriginalBuildKey;
if (factory.CanCreate(key.Type) && context.Existing == null)
{
context.Existing = factory.Create(key.Type);
var ltm = new ContainerControlledLifetimeManager();
ltm.SetValue(context.Existing);
// Find the container to add this to
IPolicyList parentPolicies;
var parentMarker = context.Policies.Get<ParentMarkerPolicy>(new NamedTypeBuildKey<ParentMarkerPolicy>(), out parentPolicies);
// TODO: add error check - if policy is missing, extension is misconfigured
// Add lifetime manager to container
parentPolicies.Set<ILifetimePolicy>(ltm, new NamedTypeBuildKey(key.Type));
// And add to LifetimeContainer so it gets disposed
parentMarker.AddToLifetime(ltm);
// Short circuit the rest of the chain, object's already created
context.BuildComplete = true;
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)