Доступ к UnityContainer из AttributeHandler
У меня есть настройки Unity для перехвата вызовов методов, когда метод украшен определенным атрибутом. Я хочу, чтобы все прокси-объекты Unity сохранялись в каждом потоке (а не были временными).
Проблема в том, что объект, созданный атрибутом художественного оформления, создается каждый раз как "новый". Я не вижу способа получить доступ к UnityContainer из атрибута. Если бы я мог, я бы создал LogHandler как сущность для каждого потока и запросил бы это через Unity. (Имеет ли это вообще смысл? Использование Unity для разрешения объектов, используемых при перехвате единства?).
Если вы запускаете этот код, счетчик выводит в логгере всегда "1". Чтобы было ясно, этот "LogHandler" - это то, что я хочу сохранить.
Как вы разрешаете объекты с помощью единства в другом месте вашего кода? Вы передаете контейнер единства? Есть ли шаблон, который я могу использовать, чтобы запросить его из любого места в моем коде?
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
namespace UnityTest2
{
class Program
{
private static UnityContainer _uC;
static void Main(string[] args)
{
_uC = new UnityContainer();
_uC.AddNewExtension<Interception>();
_uC.Configure<Interception>().SetInterceptorFor<ICalc>(new InterfaceInterceptor());
_uC.RegisterType<ICalc, Calc>( new PerThreadLifetimeManager() );
var c = _uC.Resolve<ICalc>();
Console.WriteLine(c.Add(3, 7));
Console.WriteLine(c.Sub(3, 7));
Console.ReadKey();
}
}
public class LogAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
// I want this to persist per thread
return new LogHandler();
}
}
public class LogHandler : ICallHandler
{
private int runCount = 0;
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
runCount++;
// this is always '1'
Console.WriteLine(runCount);
return getNext()(input, getNext);
}
public int Order { get; set; }
}
public interface ICalc
{
int Add(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
}
public class Calc : ICalc
{
[Log]
public int Add(int x, int y)
{
return x + y;
}
[Log]
public int Sub(int x, int y)
{
return x - y;
}
public int Mul(int x, int y)
{
return x * y;
}
}
}
1 ответ
Вы можете зарегистрировать свой обработчик вызовов в Unity с помощью PerThreadLifetimeManager во время запуска.
_uC.RegisterType<LoggingCallHandler>(new PerThreadLifetimeManager());
Затем атрибут может разрешить обработчик из контейнера:
public class LoggingAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return container.Resolve<LoggingCallHandler>();
}
}
Обычно вы не хотите передавать экземпляры контейнера, поскольку это тесно связывает ваше приложение с конкретным используемым контейнером. Это будет использовать контейнер в качестве локатора службы. Многие люди считают, что это анти-паттерн.
Атрибуты обработчика вызовов являются частью инфраструктуры Unity (для вашего приложения); они расширяют абстрактный Unity HandlerAttribute
и требуют, чтобы метод CreateHandler принял IUnityContainer, поэтому использование контейнера в HandlerAttribute не является неожиданным.