尝试使用动态类型时RuntimeBinderException

时间:2015-02-23 20:34:58

标签: c# dynamic log4net

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

问题出现在 ChangeLogLevelTo 方法中:

例外:

  

类型的例外   ' 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;
        }

1 个答案:

答案 0 :(得分:0)

假设各种Level类型都是指定类型的公共静态属性或字段,最简单的方法是使用反射:

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);
    }
}

然后将其称为

    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;
    }