C# · 12月 26, 2021

c# – Unity的自定义对象工厂扩展

我正在使用Unity IoC容器,我需要拦截对某个基本界面的Resolve的任何调用,并运行我自己的自定义代码来构造这些类型.

换句话说,在下面的示例代码中,当我调用container.Resolve< IFooN>()时,如果没有具体实现类型的实例,它调用MyFactoryFunction构造一个,否则我希望它返回缓存副本.

标准的Unity容器不能构造这些对象(更新:因为它们是.NET远程处理对象,所以具体的类不存在于本地计算机上的任何程序集中),我不想在前面创建它们用RegisterInstance存储它们.

interface IFoo : IBase { … }interface IFoo2 : IBase { … }…container.Resolve<IFoo2>();…IBase MyFactoryFunction(Type t){ …}

我假设我可以创建一个Unity扩展来做到这一点,但我想知道是否已经有一个可以借用的解决方案.

解决方法 为了完整,我应该添加另一个在Unity 2下工作的答案,因为我的其他答案不再有效.由于您需要制定自定义构建器策略,因此它的参与程度有所增加.感谢Unity项目的ctavares,他为 this thread提供了大量的帮助: 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; } }}