2016-07-13 9 views
1

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

// ... other types being registered 
container.RegisterType<ILogger>(new InjectionFactory(ResolveLogger)); 

// Custom factory method 
private ILogger ResolveLogger(IUnityContainer container) 
{ 
    // I want to know the type of the parent that requires the ILogger interface so that I can add it to my logging context (with Serilog): 
    Type parentType = ??? 
    return Log.Logger.ForContext(parentType); 
} 

Когда я создаю экземпляр класса, Serilog позволяет мне установить контекст для регистратора в этой манере:

public class MyService 
{ 
    private readonly ILogger logger; 
    public MyService(ILogger logger) 
    { 
     this.logger = logger.ForContext(this.GetType()); 
    } 
} 

После этого, все вызовы к this.logger.Information("Hello World") будет включать в себя дополнительные метаданные показ вызова был выполнен в классе MyService.

Я старался не задумываться о том, чтобы позвонить logger.ForContext(this.GetType()) в каждом классе, который потребляет логгер, если Unity сделает для меня работу.

+1

Не могли бы вы попытаться объяснить, чем вы являетесь конечной целью. Может быть, есть лучшее решение. – Michael

+0

Я уточнил вопрос с моей конкретной целью. –

+0

Не уверен, что Unity предоставляет эту информацию. Вы можете попытаться изучить некоторые настраиваемые методы распознавания или пользовательские политики или настраиваемое наращивание. Но я думаю, что Log4Net делает то, что вы хотите. – Michael

ответ

1

Я даже не думаю, что пользовательская политика даст вам то, что вам нужно. Я не уверен, что есть даже крючок, который дает вам видимость в «родительском» типе. Я могу ошибаться. Но вот альтернативное решение и то, что я использую.

Вы можете использовать дженерики, чтобы получить вызывающий тип (похожий на ForContext, который вы упомянули, но немного более изящный). И вы можете использовать [CallerMemberName], чтобы получить имя вызывающего члена (имя метода, имя свойства и т. Д.).


Как это ...

public interface ILogger<T> 
{ 
    void Write(string message, [CallerMemberName] string callingMethod = ""); 
} 

И регистрация Unity будет использовать открытые дженерики, как это ...

container.RegisterType(typeof(ILogger<>), typeof(ConsoleLogger<>)); 

А вот пример использование ...

public class MyService 
{ 
    public MyService(ILogger<MyFileService> logger) 
    { 
     // Check for nulls, set to member variable, etc. 
    } 
} 

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

Я издевался над примером here.