/// <summary>
 /// 使用指定的静态字段,初始化 <see cref="MemberAccessor{T}"/> 类的新实例,
 /// 表示指定的静态字段。
 /// </summary>
 /// <param name="field">要访问的静态字段。</param>
 public MemberAccessor(FieldInfo field)
 {
     CommonExceptions.CheckArgumentNull(field, "field");
     this.name = field.Name;
     Init(field, null);
 }
Exemple #2
0
        /// <summary>
        /// 将一个或多个枚举常数的名称、描述或数字值的字符串表示转换成等效的枚举对象。
        /// 一个参数指定该操作是否区分大小写。
        /// </summary>
        /// <param name="enumType">枚举类型。</param>
        /// <param name="value">包含要转换的值或名称的字符串。</param>
        /// <param name="ignoreCase">若要忽略大小写则为 <c>true</c>;
        /// 否则为 <c>false</c>。</param>
        /// <returns><paramref name="enumType"/> 类型的对象,其值由 <paramref name="value"/> 表示。</returns>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="value"/> 为 <c>null</c>。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="enumType"/> 不是 <see cref="System.Enum"/>。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="value"/> 是空字符串 ("") 或只包含空白。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="value"/> 是一个名称,但不是为该枚举定义的命名常量之一。</exception>
        /// <exception cref="System.OverflowException">
        /// <paramref name="value"/> 超出 <paramref name="enumType"/>
        /// 基础类型的范围。</exception>
        public static object ParseEx(Type enumType, string value, bool ignoreCase)
        {
            CommonExceptions.CheckArgumentNull(enumType, "enumType");
            CommonExceptions.CheckArgumentNull(value, "value");
            if (!enumType.IsEnum)
            {
                throw CommonExceptions.MustBeEnum("enumType", enumType);
            }
            value = value.Trim();
            if (value.Length == 0)
            {
                throw CommonExceptions.MustContainEnumInfo("value");
            }
            // 尝试对数字进行解析,这样可避免之后的字符串比较。
            ulong tmpValue;

            if (ParseString(value, out tmpValue))
            {
                return(Enum.ToObject(enumType, tmpValue));
            }
            // 尝试对描述信息进行解析。
            EnumCache        cache      = GetEnumCache(enumType);
            StringComparison comparison = ignoreCase ?
                                          StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
            ulong valueUL = 0;
            int   start   = 0;

            do
            {
                // 去除前导空白。
                while (char.IsWhiteSpace(value, start))
                {
                    start++;
                }
                int idx = value.IndexOf(',', start);
                if (idx < 0)
                {
                    idx = value.Length;
                }
                int nIdx = idx - 1;
                // 去除后面的空白。
                while (char.IsWhiteSpace(value, nIdx))
                {
                    nIdx--;
                }
                if (nIdx >= start)
                {
                    string str = value.Substring(start, nIdx - start + 1);
                    int    j   = 0;
                    // 比较常数值的名称和描述信息,先比较名称,后比较描述信息。
                    for (; j < cache.Names.Length; j++)
                    {
                        if (string.Equals(str, cache.Names[j], comparison))
                        {
                            // 与常数值匹配。
                            valueUL |= cache.Values[j];
                            break;
                        }
                    }
                    if (j == cache.Names.Length && cache.HasDescription)
                    {
                        // 比较描述信息。
                        for (j = 0; j < cache.Descriptions.Length; j++)
                        {
                            if (string.Equals(str, cache.Descriptions[j], comparison))
                            {
                                // 与描述信息匹配。
                                valueUL |= cache.Values[j];
                                break;
                            }
                        }
                    }
                    // 未识别的枚举值。
                    if (j == cache.Descriptions.Length)
                    {
                        // 尝试识别为数字。
                        if (ParseString(str, out tmpValue))
                        {
                            valueUL |= tmpValue;
                        }
                        else
                        {
                            // 不能识别为数字。
                            throw CommonExceptions.EnumValueNotFound(enumType, str);
                        }
                    }
                }
                start = idx + 1;
            } while (start < value.Length);
            return(Enum.ToObject(enumType, valueUL));
        }
 /// <summary>
 /// 使用指定的静态属性,初始化 <see cref="MemberAccessor{T}"/> 类的新实例,
 /// 表示指定的静态属性。
 /// </summary>
 /// <param name="property">要访问的静态属性。</param>
 /// <param name="nonPublic">指示是否应访问非公共属性。
 /// 如果要访问非公共属性,则为 <c>true</c>;否则为 <c>false</c>。</param>
 public MemberAccessor(PropertyInfo property, bool nonPublic)
 {
     CommonExceptions.CheckArgumentNull(property, "property");
     this.name = property.Name;
     Init(property, null, nonPublic);
 }
        /// <summary>
        /// 返回与指定标识符相关的处理器方法集合。
        /// </summary>
        /// <typeparam name="TDelegate">使用基类型调用方法的委托。</typeparam>
        /// <param name="type">在其中查找静态或实例方法的类型。</param>
        /// <param name="id">方法切换器的标识符。</param>
        /// <param name="index">方法的关键参数索引。</param>
        /// <param name="queryStatic">是否请求的是静态方法。</param>
        /// <returns>与指定标识符相关的处理器方法集合。</returns>
        private static Dictionary <Type, Delegate> GetMethods <TDelegate>(Type type, string id, int index, bool queryStatic)
        {
            Type dlgType = typeof(TDelegate);
            Tuple <bool, Type, Dictionary <Type, Delegate> > data;
            string key = string.Concat(type.FullName, "_", id);

            if (!methodDict.TryGetValue(key, out data))
            {
                MethodInfo[]      methods = type.GetMethods(MethodFlags);
                List <MethodInfo> list    = new List <MethodInfo>();
                for (int i = 0; i < methods.Length; i++)
                {
                    if (methods[i].GetCustomAttributes(typeof(ProcessorAttribute), true)
                        .Cast <ProcessorAttribute>().Any(s => s.Id == id))
                    {
                        list.Add(methods[i]);
                    }
                }
                int cnt = list.Count;
                if (cnt == 0)
                {
                    throw CommonExceptions.ProcessorNotFound("type", type, id);
                }
                bool isStatic = list[0].IsStatic;
                for (int i = 1; i < cnt; i++)
                {
                    if (list[i].IsStatic != isStatic)
                    {
                        throw CommonExceptions.ProcessorMixed("type", type, id);
                    }
                }
                Dictionary <Type, Delegate> dict = new Dictionary <Type, Delegate>();
                Type newDlgType = dlgType;
                if (!isStatic)
                {
                    newDlgType = GetInstanceDlgType(newDlgType);
                }
                for (int i = 0; i < cnt; i++)
                {
                    Type     keyType = list[i].GetParameters()[index].ParameterType;
                    Delegate dlg     = DelegateBuilder.CreateDelegate(newDlgType, list[i], false);
                    if (dlg == null)
                    {
                        throw CommonExceptions.DelegateCompatible(list[i].ToString(), dlgType);
                    }
                    dict.Add(keyType, dlg);
                }
                data = new Tuple <bool, Type, Dictionary <Type, Delegate> >(isStatic, dlgType, dict);
                methodDict.Add(key, data);
            }
            if (data.Item1 != queryStatic)
            {
                throw CommonExceptions.ProcessorMismatch("type", type, id);
            }
            if (data.Item2 != dlgType)
            {
                // 检查委托参数。
                ParameterInfo[] paramInfos    = data.Item2.GetMethod("Invoke").GetParameters();
                ParameterInfo[] dlgParamInfos = dlgType.GetMethod("Invoke").GetParameters();
                if (paramInfos.Length != dlgParamInfos.Length)
                {
                    throw CommonExceptions.DelegateCompatible("TDelegate", dlgType);
                }
                for (int i = 0; i < paramInfos.Length; i++)
                {
                    if (paramInfos[i].ParameterType != dlgParamInfos[i].ParameterType)
                    {
                        throw CommonExceptions.DelegateCompatible("TDelegate", dlgType);
                    }
                }
            }
            return(data.Item3);
        }
Exemple #5
0
        /// <summary>
        /// 基于指定的判据,从给定的属性集中选择一个属性。
        /// </summary>
        /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选属性集。</param>
        /// <param name="returnType">匹配属性必须具有的返回值。</param>
        /// <param name="indexes">所搜索的属性的索引类型。</param>
        /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param>
        /// <returns>如果找到,则为匹配的属性;否则为 <c>null</c>。</returns>
        public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType,
                                                    Type[] indexes, ParameterModifier[] modifiers)
        {
            CommonExceptions.CheckArgumentNull(match, "match");
            if (match.Length == 0)
            {
                return(null);
            }
            int idxLen = indexes == null ? 0 : indexes.Length;

            // 构造属性信息数组。
            MatchInfo[] infos = new MatchInfo[match.Length];
            int         idx   = 0;

            for (int i = 0; i < match.Length; i++)
            {
                if (match[i] != null)
                {
                    ParameterInfo[] parameters = match[i].GetIndexParameters();
                    // 匹配属性类型与索引参数。
                    if (parameters.Length == idxLen && CheckParameters(infos[i], indexes, idxLen) &&
                        CanChangeType(match[i].PropertyType, returnType))
                    {
                        infos[idx] = new MatchInfo(parameters, MethodExt.GetParamOrder(idxLen));
                        match[idx] = match[i];
                        idx++;
                    }
                }
            }
            if (idx == 0)
            {
                return(null);
            }
            if (idx == 1)
            {
                return(match[0]);
            }
            // 多个可匹配属性,寻找匹配的最好的属性。
            int  min   = 0;
            bool ambig = false;

            for (int i = 1; i < idx; i++)
            {
                // 先比较属性类型。
                int cmp = FindMostSpecificType(match[min].PropertyType, match[i].PropertyType, returnType);
                if (cmp == 0 && indexes != null)
                {
                    // 再比较属性参数。
                    cmp = FindMostSpecific(infos[min], infos[i], indexes);
                }
                if (cmp == 0)
                {
                    // 最后比较定义的层级深度。
                    cmp = CompareHierarchyDepth(match[min], match[i]);
                    if (cmp == 0)
                    {
                        ambig = true;
                    }
                }
                if (cmp == 2)
                {
                    ambig = false;
                    min   = i;
                }
            }
            if (ambig)
            {
                throw CommonExceptions.AmbiguousMatchProperty();
            }
            return(match[min]);
        }
Exemple #6
0
        /// <summary>
        /// 基于提供的参数,从给定的方法集中选择要调用的方法。
        /// </summary>
        /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选方法集。</param>
        /// <param name="args">传入的参数。</param>
        /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param>
        /// <param name="culture">一个 <see cref="System.Globalization.CultureInfo"/> 实例,
        /// 用于在强制类型的联编程序实现中控制数据类型强制。</param>
        /// <param name="names">参数名(如果匹配时要考虑参数名)或 <c>null</c>(如果要将变量视为纯位置)。</param>
        /// <param name="state">方法返回之后,<paramref name="state"/> 包含一个联编程序提供的对象,
        /// 用于跟踪参数的重新排序。</param>
        /// <returns>匹配的方法。</returns>
        public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args,
                                                ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
        {
            if (match == null)
            {
                throw CommonExceptions.ArgumentNull("match");
            }
            if (match.Length == 0)
            {
                throw CommonExceptions.ArrayEmpty("match");
            }
            // 检查参数名称数组,不能出现名称相同的两个参数。
            if (names != null)
            {
                CheckNames(names);
            }
            // 构造方法信息数组。
            MatchInfo[] infos = new MatchInfo[match.Length];
            MatchInfo   info  = null;
            int         idx   = 0;

            for (int i = 0; i < match.Length; i++)
            {
                if (match[i] != null)
                {
                    info = new MatchInfo(match[i]);
                    int len = info.Parameters.Length > args.Length ? info.Parameters.Length : args.Length;
                    if (names == null)
                    {
                        info.ParamOrder = info.ParamOrderRev = MethodExt.GetParamOrder(len);
                    }
                    else
                    {
                        info.ParamOrder = new int[len];
                        // 根据 names 创建参数顺序。
                        if (!CreateParamOrder(info.ParamOrder, info.Parameters, names))
                        {
                            continue;
                        }
                    }
                    infos[idx++] = info;
                }
            }
            if (idx == 0)
            {
                // 没有可匹配的方法。
                state = null;
                return(null);
            }
            Type[] types = new Type[args.Length];
            for (int i = 0; i < args.Length; i++)
            {
                // types[i] 为 null 表示可以匹配任何引用类型。
                if (args[i] != null)
                {
                    types[i] = args[i].GetType();
                }
            }
            info = SelectMethod(bindingAttr, infos, idx, types);
            if (info == null)
            {
                // 没有可匹配的方法。
                state = null;
                return(null);
            }
            UpdateArgs(info, ref args, names != null, out state);
            return(info.Method);
        }
Exemple #7
0
        /// <summary>
        /// 基于指定的判据,从给定的字段集中选择一个字段。
        /// </summary>
        /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选字段集。</param>
        /// <param name="value">用于定位匹配字段的字段值。</param>
        /// <param name="culture">一个 <see cref="System.Globalization.CultureInfo"/> 实例,
        /// 用于在强制类型的联编程序实现中控制数据类型强制。</param>
        /// <returns>匹配的字段。</returns>
        public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value,
                                              CultureInfo culture)
        {
            int  idx       = 0;
            Type valueType = null;

            if (value != null)
            {
                valueType = value.GetType();
            }
            bool setField = (bindingAttr & BindingFlags.SetField) != 0;

            if (setField)
            {
                // 在设置 SetField 标志时,根据 value 的类型进行选择。
                for (int i = 0; i < match.Length; i++)
                {
                    if (CanChangeType(match[i].FieldType, valueType))
                    {
                        match[idx++] = match[i];
                    }
                }
                if (idx == 0)
                {
                    // 没有可匹配的字段。
                    return(null);
                }
                else if (idx > 1 && valueType != null)
                {
                    // 多个可匹配字段,尝试寻找类型匹配的最好的字段。
                    int len = idx;
                    idx = 1;
                    for (int i = 1; i < len; i++)
                    {
                        // 尝试进一步匹配字段类型。
                        int cmp = FindMostSpecificType(match[0].FieldType, match[i].FieldType, valueType);
                        if (cmp == 0)
                        {
                            match[idx++] = match[i];
                        }
                        else if (cmp == 2)
                        {
                            match[0] = match[i];
                            idx      = 1;
                        }
                    }
                }
            }
            else
            {
                idx = match.Length;
            }
            // 多个可匹配字段,寻找定义深度最深的字段。
            int  min   = 0;
            bool ambig = false;

            for (int i = 1; i < idx; i++)
            {
                // 比较定义的层级深度。
                int cmp = CompareHierarchyDepth(match[min], match[i]);
                if (cmp == 0)
                {
                    ambig = true;
                }
                else if (cmp == 2)
                {
                    min   = i;
                    ambig = false;
                }
            }
            if (ambig)
            {
                throw CommonExceptions.AmbiguousMatchField();
            }
            return(match[min]);
        }