2016-11-02 3 views
0

Я использую простой инжектор в качестве контейнера IoC. Я хотел бы ввести в свой логгер классов, основываясь на наличии области выполнения. Должен быть один регистратор по умолчанию (singleton) и другие, основанные на моем контексте.Регистрация реализации на основе образа жизни simpleinjector

Я уже пробовал что-то вроде этого:

container.RegisterConditional(typeof(ILogger), 
    x => typeof(NContextLogger<>).MakeGenericType(x.Consumer.ImplementationType), 
    Lifestyle.Scoped, 
    x => container.GetCurrentExecutionContextScope() != null); 

container.RegisterConditional(typeof(ILogger), 
    x => typeof(NLogger<>).MakeGenericType(x.Consumer.ImplementationType), 
    Lifestyle.Singleton, 
    x => container.GetCurrentExecutionContextScope() == null); 

Проблема с созданием любого экземпляра NContextLogger<>. Потому что когда он создает NLogger<>, который является singleton, simpleinjector не пытается создать экземпляр NContextLogger.

+0

Я должен сказать, что я нахожу это довольно странное требование. Почему нужно разрешать объекты вне контекста области контекста активного выполнения? – Steven

ответ

2

Предикат, поставляемый в RegisterConditional, не может использоваться для принятия решения во время выполнения, поскольку результаты предиката кэшируются и записываются в дерево выражений и скомпилированные делегаты. Наличие GetCurrentExecutionContextScope() Lifestyle.Scoped.GetCurrentScope(Container) однако является решением во время выполнения.

Решения, основанные на условиях выполнения, не должны выполняться при построении графика объекта (по той же причине, что и runtime data shouldn't be injected into components).

Вместо принятия решений, основанных на условиях выполнения во время построения графа объектов, эти решения следует отложить до тех пор, пока не будет построен граф объекта. Самый очевидный способ сделать это путем введения прокси-класс:

public sealed class ProxyLogger<T> : ILogger 
{ 
    private readonly Container container; 

    public ProxyLogger(Container container) { 
     this.container = container; 
    } 

    // Implement ILogger method(s) 
    public void Log(string message) => Logger.Log(message); 

    private ILogger Logger => Lifestyle.Scoped.GetCurrentScope(container) == null 
     ? container.GetInstance<NLogger<T>>() 
     : container.GetInstance<NContextLogger<T>>(); 
} 

Используя этот прокси-класс, вы можете сделать следующие регистрации, чтобы удовлетворить ваши требования:

container.RegisterConditional(typeof(ILogger), 
    c => typeof(ProxyLogger<>).MakeGenericType(x.Consumer.ImplementationType), 
    Lifestyle.Singleton, 
    c => true); 

container.Register(typeof(NLogger<>), typeof(NLogger<>), Lifestyle.Singleton); 
container.Register(typeof(NContextLogger<>), typeof(NContextLogger<>),Lifestyle.Singleton); 
+0

Спасибо. ProxyLogger - вещь, которую я искал. – Raik

Смежные вопросы