Unity Container: использование PerResolveLifetimeManager и пользовательский перехват - PullRequest
7 голосов
/ 17 июня 2010

Я пытаюсь реализовать свой собственный перехват, все еще используя контейнер Unity.Я хочу сделать это таким образом, чтобы он уважал время жизни менеджера.то есть, если это PerResolveLifetimeManager, то я хочу один раз обернуть экземпляр, и я хочу, чтобы этот обернутый экземпляр использовался на протяжении всего разрешения.

До сих пор я реализовал BuilderStrategy, который добавляю в свой контейнер с помощью пользовательского класса UnityContainerExtension (я передаю PostInitialization методу AddNew; я не уверен, какое значение является наиболее подходящим, но это, похоже, работает).В переопределении PostBuildUp в моем BuilderStrategy я заменяю context.Existing на мое упакованное значение.

Когда я использую это с временем жизни PerResolve, происходит одна перенос, но только первое использование зависимости получает завернутый экземпляр иостальные получают не завернутый экземпляр.т. е. если мой ctor использует IFoo foo1 и IFoo foo2, то только foo1 является моим обернутым экземпляром, а foo2 - развернутым экземпляром.

Вот пример репродукции (для простоты я использую экземпляр другого класса, Foo2вместо переноса):

public class MyInterception : UnityContainerExtension
{
    protected override void Initialize()
    {
        Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.PostInitialization);
    }
}

public class MyInterceptionStrategy : BuilderStrategy
{
    public override void PostBuildUp(IBuilderContext context)
    {
        if (!context.OriginalBuildKey.Type.IsInterface)
        {
            return;
        }

        context.Existing = new Foo2();
    }
}

public class Bar
{
    public Bar(IFoo f1, IFoo f2, IFoo f3)
    {
    }
}

public interface IFoo
{
}

public class Foo1 : IFoo
{
}

public class Foo2 : IFoo
{
}

public void Main()
{
    UnityContainer container = new UnityContainer();
    container.AddNewExtension<MyInterception>();
    container.RegisterType(typeof (IFoo), typeof (Foo1), new PerResolveLifetimeManager());

    container.Resolve<Bar>();
}

Если вы поместили точку останова в PostBuildUp и в конструкторе Bar и отладили Main до разрешения Bar, вы увидите, что PostBuildUp вызывается только один раз.Однако в конструкторе Bar f1 является экземпляром Foo2 («обернутый» экземпляр), в то время как f2 и f3 являются экземплярами Foo1 (развернутый).

Мне было интересно, возможно ли то, что я хочу, и выбираю ли я правильный подход?Мои проблемы связаны с временем жизни и / или UnityBuildStage, для которого я добавил BuilderStrategy?

Спасибо

1 Ответ

2 голосов
/ 11 ноября 2010

Вы делаете стратегию перехвата слишком поздно в стратегии сборки.К сожалению, в настоящее время у меня нет более подробной причины для , почему код ведет себя так в сборке ObjectBuilder .

Надеюсь, я вернусь, когда у меня будет больше времени для анализа Unity ObjectBuilder, но для временного решения вашей проблемы просто измените значение перечисления UnityBuildStage с PostInitialization to Настройка или TypeMapping

Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.Setup);

Мой полный код:

using System;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.ObjectBuilder;

namespace UnityInterceptors
{
    class Program
    {
        public class MyInterception : UnityContainerExtension
        {
            protected override void Initialize()
            {
                Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.Setup);
            }
        }
        public class MyInterceptionStrategy : BuilderStrategy
        {
            public override void PostBuildUp(IBuilderContext context)
            {
                if (!context.OriginalBuildKey.Type.IsInterface)
                {
                    return;
                }

                context.Existing = new Foo2();
            }
        }

        public class Bar
        {
            public Bar(IFoo f1, IFoo f2, IFoo f3)
            {
                Console.WriteLine(f1.GetType().Name);
                Console.WriteLine(f2.GetType().Name);
                Console.WriteLine(f3.GetType().Name);
            }
        }

        public interface IFoo
        {
        }

        public class Foo1 : IFoo
        {
        }

        public class Foo2 : IFoo
        {
        }

        public static void Main()
        {
            UnityContainer container = new UnityContainer();
            container.AddNewExtension<MyInterception>();
            container.RegisterType(typeof(IFoo), typeof(Foo1), new PerResolveLifetimeManager());

            container.Resolve<Bar>();

            Console.ReadLine();
        }
    }
}
  • Также обратите внимание, что я использую библиотеку Unity 2.0.Возможно, это ошибка определенного типа.
...