exercise: 反射获取指定的属性值 --CSharp
/// <summary> /// 放到 public static 非索引 property上 /// </summary> [AttributeUsage(AttributeTargets.Property, Inherited = true)] class CheckedPropertyAttribute: Attribute { /// <summary> /// 必要的访问修饰 /// </summary> private const BindingFlags REQUIRED_BINDING_FLAGS = BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty; /// <summary> /// 被标记的别名 /// </summary> public string AliasName { get; set; } /// <summary> /// 进行排序, 在有顺序要求的地方设置该属性 /// </summary> public int Order { get; set; } = 0; public CheckedPropertyAttribute() : this(string.Empty) { } public CheckedPropertyAttribute(string aliasName) { this.AliasName = aliasName; } /// <summary> /// 带有 CheckedProperty 的属性, 如果没有任何匹配的属性, 则返回数组长度为 0 /// </summary> /// <typeparam name="T">被搜索属性的类型</typeparam> /// <param name="holderType">包含 被搜索属性的 类型</param> /// <returns>item1 = propertyName, item2 = aliasName, item3 = propertyValue </returns> public static Tuple<string, string, T>[] CollectChecked<T>(Type holderType) { return holderType.GetProperties(REQUIRED_BINDING_FLAGS) .Select(ExtractInfos) .Where((t) => t != null) .OrderBy((t) => t.Item2.Order) .Select((t) => new Tuple<string, string, T>(t.Item1, t.Item2.AliasName, t.Item3)) .ToArray(); // local functions Tuple<string, CheckedPropertyAttribute, T> ExtractInfos(PropertyInfo pi) { if (IsIndexParameter(pi) || !TryGetPropertyValue(pi, out T propVal) || !TryGetAttr(pi, out CheckedPropertyAttribute cpa)) { return null; } return new Tuple<string, CheckedPropertyAttribute, T>(pi.Name, cpa, propVal); } bool IsIndexParameter(PropertyInfo pi) { var paramInfos = pi.GetIndexParameters(); return (paramInfos.Length != 0); } bool TryGetPropertyValue(PropertyInfo pi, out T propVal) { object pVal = pi.GetValue(null, null); bool valGetted = typeof(T).IsAssignableFrom(pi.PropertyType); propVal = valGetted ? (T)pVal : default(T); return valGetted; } bool TryGetAttr(PropertyInfo pi, out CheckedPropertyAttribute attr) { attr = (CheckedPropertyAttribute)GetCustomAttribute( pi, typeof(CheckedPropertyAttribute), true); return (attr != null); } } } // class
--- THE END ---