Unity的自定义对象工厂扩展 [英] Custom object factory extension for Unity

查看:99
本文介绍了Unity的自定义对象工厂扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Unity IoC容器,并且需要拦截某个特定基本接口对Resolve的所有调用,并运行自己的自定义代码来构造这些类型.

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.

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

In other words, in the sample code below, when I call container.Resolve<IFooN>(), if it hasn't got an instance of the concrete implementing type, it calls MyFactoryFunction to construct one, otherwise I want it to return the cached copy.

标准Unity容器无法构造这些对象(更新:,因为它们是.NET远程处理对象,因此具体类在本地计算机上的任何程序集中都不存在),并且我不想先创建它们并将它们存储在RegisterInstance中.

The standard Unity container is not able to construct these objects (update: because they are .NET remoting objects, so the concrete classes do not exist in any assembly on the local computer), and I don't want to create them up front and store them with RegisterInstance.

interface IFoo : IBase { ... }
interface IFoo2 : IBase { ... }

...
container.Resolve<IFoo2>();

...
IBase MyFactoryFunction(Type t)
{
    ...
}

我假设我可以创建一个Unity扩展来执行此操作,但是我想知道是否已经有可以借用的解决方案了.

I'm assuming I can create a Unity extension to do this, but I was wondering if there is already a solution out there I can borrow.

推荐答案

出于完整性考虑,我应该添加另一个在Unity 2下有效的答案,因为我的其他答案不再有效.因为您需要制定自定义构建器策略,所以它的参与程度略高.感谢Unity项目中的ctavares,他为实现该线程此线程提供了很多帮助:

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<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;
        }
    }
}

这篇关于Unity的自定义对象工厂扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆