Exemple #1
0
        /// <summary>
        /// 基于指定的判据,从给定的字段集中选择一个字段。
        /// </summary>
        /// <param name="bindingAttr"><see cref="BindingFlags"/> 值的按位组合。</param>
        /// <param name="match">用于匹配的候选字段集。<see cref="PowerBinder"/> 的实现会更改此数组的顺序。</param>
        /// <param name="value">用于定位匹配字段的字段值。</param>
        /// <param name="culture">一个 <see cref="CultureInfo"/> 实例,
        /// 用于在强制类型的联编程序实现中控制数据类型强制。</param>
        /// <returns>匹配的字段。</returns>
        /// <exception cref="ArgumentNullException"><paramref name="match"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentException"><paramref name="match"/> 为空数组。</exception>
        /// <exception cref="ArgumentException"><paramref name="match"/> 中包含为 <c>null</c> 的元素。</exception>
        /// <exception cref="AmbiguousMatchException"><paramref name="match"/> 包含多个与 <paramref name="value"/>
        /// 匹配程度相同的字段。</exception>
        /// <exception cref="MissingFieldException"><paramref name="bindingAttr"/> 包含
        /// <see cref="BindingFlags.SetField"/>,且 <paramref name="match"/> 不包含任何可接受 <paramref name="value"/>
        /// 的字段。</exception>
        public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, [CanBeNull] object value,
                                              CultureInfo culture)
        {
            CommonExceptions.CheckCollectionItemNull(match, "match");
            Contract.EndContractBlock();
            int length = 0;

            if (bindingAttr.HasFlag(BindingFlags.SetField))
            {
                // 在设置 SetField 标志时,根据 value 的类型进行选择。
                Type valueType = value == null ? null : value.GetType();
                for (int i = 0; i < match.Length; i++)
                {
                    if (CanChangeType(valueType, match[i].FieldType))
                    {
                        match[length++] = match[i];
                    }
                }
                if (length == 0)
                {
                    throw CommonExceptions.MissingField();
                }
                if (length > 1 && valueType != null)
                {
                    // 多个可匹配字段,尝试寻找类型最匹配的字段。
                    length = FilterMember(match, length, (firstField, secondField) =>
                                          CompareType(firstField.FieldType, secondField.FieldType, valueType));
                }
            }
            else
            {
                length = match.Length;
            }
            FieldInfo best = GetDeepestMember(match, length);

            if (best == null)
            {
                throw CommonExceptions.AmbiguousMatchField();
            }
            return(best);
        }
Exemple #2
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]);
        }