Custom object factory extension for Unity

后端 未结 4 1257
你的背包
你的背包 2021-01-02 06:05

I am using the Unity IoC container, and I need to intercept any calls to Resolve for a certain base interface, and run my own custom code to construct those types.

4条回答
  •  清酒与你
    2021-01-02 06:27

    For completeness, I should add another answer that works under Unity 2, since my other answer no longer works. It is slightly more involved since you need to make a custom builder policy. Thanks to ctavares from the Unity project who provided lots of help on this thread in implementing this:

    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(new ParentMarkerPolicy(Context.Lifetime), new NamedTypeBuildKey());
        }
    }
    
    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(new NamedTypeBuildKey(), out parentPolicies);
    
                // TODO: add error check - if policy is missing, extension is misconfigured
    
                // Add lifetime manager to container
                parentPolicies.Set(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;
            }
        }
    }
    

提交回复
热议问题