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

RuntimeBinderException when trying to use dynamic type

我正在尝试在我已设置的当前日志模式中实施 log4net,但在尝试将我的枚举 LogLevel 转换为 log4net 级别 class 时我 运行 遇到了一些问题 class。

问题在于 ChangeLogLevelTo 方法:

异常:

An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code

Additional information: System.Reflection.TypeInfo does not contain any definition for info.

我是不是想错了,或者我可以这样解决:

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

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

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