解决通用的Microsoft.Extensions.Logging.ILogger< T>与Unity一起使用-获取InvalidCastException [英] Resolve generic Microsoft.Extensions.Logging.ILogger<T> with Unity - get InvalidCastException

查看:716
本文介绍了解决通用的Microsoft.Extensions.Logging.ILogger< T>与Unity一起使用-获取InvalidCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在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&lt; T&gt;与Unity一起使用-获取InvalidCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆