我正在尝试在Unity(版本4)中注册通用ILogger(来自Microsoft.Extensions.Logging,而不是来自Serilog).
I am trying to register a generic ILogger (from Microsoft.Extensions.Logging, not from Serilog) in Unity (version 4).
我有以下课程:
public class MyClass { private readonly Microsoft.Extensions.Logging.ILogger<MyClass> _logger; public MyClass(Microsoft.Extensions.Logging.ILogger<MyClass> logger) { _logger = logger; } }以及以下Unity注册和测试:
And the following Unity registrations and test:
// Arrange IUnityContainer container = new UnityContainer(); // provider from Serilog.Extensions.Logging nuget package var provider = new Serilog.Extensions.Logging.SerilogLoggerProvider(); container.RegisterType(typeof(Microsoft.Extensions.Logging.ILogger<>), new InjectionFactory((ctr, type, name) => { var loggerType = type.GetGenericArguments()[0].FullName; Microsoft.Extensions.Logging.ILogger logger = provider.CreateLogger(loggerType); return logger; })); container.RegisterType<MyClass, MyClass>(); // just for demo purpose. // Assert container.Resolve<MyClass>();对我来说这似乎还可以,很糟糕,解决时我遇到了以下错误:
This seems OK to me, too bad I am having the following error when resolving:
异常是:InvalidCastException-无法将类型为'Serilog.Extensions.Logging.SerilogLogger'的对象转换为类型为'Microsoft.Extensions.Logging.ILogger`1 [MyNamespace.MyClass]'.
Exception is: InvalidCastException - Unable to cast object of type 'Serilog.Extensions.Logging.SerilogLogger' to type 'Microsoft.Extensions.Logging.ILogger`1[MyNamespace.MyClass]'.
如何解决此问题?
完全例外:
Microsoft.Practices.Unity.ResolutionFailedException:依赖关系的解析失败,请键入="MyNamespace.MyClass",名称=(none)". 发生以下异常:解析构造函数MyNamespace.MyClass(Microsoft.Extensions.Logging.ILogger 1[[MyNamespace.MyClass, MyNamespace.Infra.UnitTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=edbaf8e9a324553f]] logger). Exception is: InvalidCastException - Unable to cast object of type 'Serilog.Extensions.Logging.SerilogLogger' to type 'Microsoft.Extensions.Logging.ILogger 1 [MyNamespace.MyClass]'的参数记录器".
Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "MyNamespace.MyClass", name = "(none)". Exception occurred while: Resolving parameter "logger" of constructor MyNamespace.MyClass(Microsoft.Extensions.Logging.ILogger1[[MyNamespace.MyClass, MyNamespace.Infra.UnitTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=edbaf8e9a324553f]] logger). Exception is: InvalidCastException - Unable to cast object of type 'Serilog.Extensions.Logging.SerilogLogger' to type 'Microsoft.Extensions.Logging.ILogger1[MyNamespace.MyClass]'.
更新
使用Microsoft.Extensions.DependencyInjection时,此方法有效:
Update
when using Microsoft.Extensions.DependencyInjection, this works:
// Arrange var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection() .AddLogging(builder => builder.AddSerilog()) .AddTransient<MyClass, MyClass>(); var serviceProvider = serviceCollection.BuildServiceProvider(); // Assert serviceProvider.GetService<MyClass>();所以我尝试使用Unity而不是Microsoft.Extensions.DependencyInjection
So I try to get this working with Unity instead of Microsoft.Extensions.DependencyInjection
不幸的是,Unity没有AddSerilog,我已经绑定到Unity
Unfortunately there is no AddSerilog for Unity and I'm bound to Unity
推荐答案我借助MakeGenericMethod和辅助方法解决了此问题:
I resolved this with the help of MakeGenericMethod and a helper method:
private static ILogger<T> CreateLogger<T>(ILoggerFactory factory) { return new Logger<T>(factory); }最后的代码(没有反射缓存等):
And the final code (without reflection caching etc):
// Arrange IUnityContainer container = new UnityContainer(); var logfactory = new LoggerFactory(); var provider = new Serilog.Extensions.Logging.SerilogLoggerProvider(); logfactory.AddProvider(provider); container.RegisterType(typeof(Microsoft.Extensions.Logging.ILogger<>), new InjectionFactory((ctr, type, name) => { var loggerType = type.GetGenericArguments()[0]; var myType = this.GetType(); var createLoggerMethod1 = myType.GetMethod(nameof(CreateLogger),BindingFlags.Static | BindingFlags.NonPublic); var createLoggerMethod = createLoggerMethod1.MakeGenericMethod(loggerType); var logger = createLoggerMethod.Invoke(this, new object[] {logfactory}); return logger; })); container.RegisterType<MyClass, MyClass>(); // Assert container.Resolve<MyClass>();更多推荐
解决通用的Microsoft.Extensions.Logging.ILogger< T>与Unity一起使用
发布评论