C# 尝试使用动态类型时出现RuntimeBinderException

C# 尝试使用动态类型时出现RuntimeBinderException,c#,dynamic,log4net,C#,Dynamic,Log4net,我试图在我的当前日志模式中实现log4net,我已经设置好了,但是在尝试将我的enum LogLevel转换为log4net的Level类时遇到了一些问题 问题在于将loglevel更改为方法: 例外情况: 类型的例外 中出现“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException” System.Core.dll,但未在用户代码中处理 其他信息:System.Reflection.TypeInfo不包含 信息的任何定义 我是否认为这是错误的,

我试图在我的当前日志模式中实现log4net,我已经设置好了,但是在尝试将我的enum LogLevel转换为log4net的Level类时遇到了一些问题

问题在于将loglevel更改为方法:

例外情况:

类型的例外 中出现“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException” System.Core.dll,但未在用户代码中处理

其他信息:System.Reflection.TypeInfo不包含 信息的任何定义

我是否认为这是错误的,或者我可以这样解决它:

public class Log4NetTargets : ILogTarget
    {

        public void Log(LogLevel logLevel, string correlationId, Type type, string member, string message, IDictionary<string, string> customData)
        {
            var log = log4net.LogManager.GetLogger(type);
            var level = ChangeLogLevelTo<Level>(logLevel);

            log.Logger.Log(type, level, string.Format("ID: {0} MESSAGE: {1} CUSTOM DATA: {2}", correlationId, message, customData ), new Exception());
        }

        public void Log(LogLevel logLevel, string correlationId, Type type, string member, Exception exception, IDictionary<string, string> customData)
        {
            var log = log4net.LogManager.GetLogger(type);
            var level = ChangeLogLevelTo<Level>(logLevel);

            log.Logger.Log(type, level, string.Format("ID: {0} EXCEPTION: {1} CUSTOM DATA: {2}", correlationId, exception, customData), new Exception());
        }

        private T ChangeLogLevelTo<T>(LogLevel logLevel)
        {
            var result = default(T);

            dynamic dynamicType = typeof(T);

            switch (logLevel)
            {
                case LogLevel.Error:
                    result = dynamicType.Error;
                    break;
                case LogLevel.Info:
                    result = dynamicType.Info;
                    break;
                case LogLevel.Trace:
                    result = dynamicType.Trace;
                    break;
                case LogLevel.Warning:
                    result = dynamicType.Warn;
                    break;
            }

            return result;
        }
公共类Log4NetTargets:ILogTarget
{
公共无效日志(日志级别、日志级别、字符串关联ID、类型、字符串成员、字符串消息、IDictionary customData)
{
var log=log4net.LogManager.GetLogger(类型);
var级别=变更LogLevelTo(logLevel);
log.Logger.log(类型、级别、字符串.Format(“ID:{0}消息:{1}自定义数据:{2}”、correlationId、消息、自定义数据)、新异常();
}
公共无效日志(日志级别、日志级别、字符串关联ID、类型、字符串成员、异常、IDictionary customData)
{
var log=log4net.LogManager.GetLogger(类型);
var级别=变更LogLevelTo(logLevel);
log.Logger.log(类型、级别、字符串.Format(“ID:{0}异常:{1}自定义数据:{2}”、correlationId、异常、自定义数据)、新异常();
}
私有T ChangeLogLevelTo(LogLevel LogLevel)
{
var结果=默认值(T);
动态类型=类型(T);
开关(日志级别)
{
案例日志级别。错误:
结果=dynamicType.Error;
打破
案例日志级别。信息:
结果=dynamicType.Info;
打破
案例日志级别。跟踪:
结果=dynamicType.Trace;
打破
案例日志级别。警告:
结果=dynamicType.Warn;
打破
}
返回结果;
}

假设各种
级别
类型都是指定类型上的公共静态属性或字段,实现这一点的最简单方法是使用反射:

public static class TypeExtensions
{
    public static T GetStaticPropertyValueOfType<T>(this Type type, string name)
    {
        var property = type.GetProperty(name, BindingFlags.Public | BindingFlags.Static);
        if (property != null 
            && property.GetIndexParameters().Length == 0
            && typeof(T).IsAssignableFrom(property.PropertyType) 
            && property.GetGetMethod(true) != null)
        {
            return (T)property.GetGetMethod(true).Invoke(null, new object [0]);
        }

        var field = type.GetField(name, BindingFlags.Public | BindingFlags.Static);
        if (field != null
            && typeof(T).IsAssignableFrom(field.FieldType))
            return (T) field.GetValue(null);

        return default(T);
    }
}
公共静态类类型扩展
{
公共静态T GetStaticPropertyValueOfType(此类型,字符串名称)
{
var property=type.GetProperty(名称,BindingFlags.Public | BindingFlags.Static);
if(属性!=null
&&property.GetIndexParameters().Length==0
&&typeof(T).IsAssignableFrom(property.PropertyType)
&&property.getMethod(true)!=null)
{
return(T)property.getMethod(true).Invoke(null,新对象[0]);
}
var field=type.GetField(名称,BindingFlags.Public | BindingFlags.Static);
如果(字段!=null
&&typeof(T).IsAssignableFrom(field.FieldType))
返回(T)字段。GetValue(null);
返回默认值(T);
}
}
然后像这样称呼它

    private T ChangeLogLevelTo<T>(LogLevel logLevel)
    {
        var result = default(T);

        switch (logLevel)
        {
            case LogLevel.Error:
                result = typeof(T).GetStaticPropertyValueOfType<T>("Error");
                break;
            case LogLevel.Info:
                result = typeof(T).GetStaticPropertyValueOfType<T>("Info");
                break;
            case LogLevel.Trace:
                result = typeof(T).GetStaticPropertyValueOfType<T>("Trace");
                break;
            case LogLevel.Warning:
                result = typeof(T).GetStaticPropertyValueOfType<T>("Warn");
                break;
        }

        return result;
    }
private T ChangeLogLevelTo(LogLevel LogLevel)
{
var结果=默认值(T);
开关(日志级别)
{
案例日志级别。错误:
结果=类型(T).GetStaticPropertyValueOfType(“错误”);
打破
案例日志级别。信息:
结果=类型(T).GetStaticPropertyValueOfType(“信息”);
打破
案例日志级别。跟踪:
结果=类型(T).GetStaticPropertyValueOfType(“跟踪”);
打破
案例日志级别。警告:
结果=类型(T).GetStaticPropertyValueOfType(“警告”);
打破
}
返回结果;
}

1)为什么
ChangeLogLevelTo
需要通用?2)
dynamicdynamictype=typeof(T);
不起作用,因为它没有名为
Info
等的属性。实际上,它不需要是泛型的。我正试图使它泛型化,这样我就不需要使用两个或更多看起来几乎相同的switch语句。将来我想再实现一个日志框架,然后我需要再次这样做。谢谢!现在我如果干燥比速度更重要,则需要设计:)