C#泛型类获取带自定义Step属性的模型属性集合
实现方案:泛型类获取带
StepAttribute的属性集合 这事儿用反射就能轻松搞定!我们可以写一个泛型类,通过.NET的反射机制遍历目标模型的属性,筛选出标记了StepAttribute的属性,甚至可以按StepName进行分组查询。下面是完整的实现方案:
1. 优化你的StepAttribute(可选,但更规范)
你原来的StepAttribute可以简化成自动属性,还可以加个带参数的构造函数,标记属性时会更简洁:
public class StepAttribute : Attribute { public string StepName { get; set; } // 可选:添加带参数的构造函数,直接指定StepName public StepAttribute(string stepName) { StepName = stepName; } }
这样你的模型可以写成更简洁的形式:
public class MobileKeyViewData { [Step("PersonalData")] public int PhoneNumber { get; set; } [Step("PersonalData")] public string Email { get; set; } [Step("Confirmation")] public int Code { get; set; } }
2. 泛型类核心实现
这个泛型类提供了两个核心方法:获取所有带StepAttribute的属性,以及根据指定StepName过滤属性:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; public class StepPropertyHelper<T> where T : class { /// <summary> /// 获取模型中所有标记了StepAttribute的属性 /// </summary> /// <returns>带StepAttribute的属性集合</returns> public static IEnumerable<PropertyInfo> GetAllStepProperties() { var modelType = typeof(T); // 只获取公共实例属性(符合你的模型属性定义) return modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(prop => Attribute.IsDefined(prop, typeof(StepAttribute))) .ToList(); } /// <summary> /// 根据指定的StepName获取对应属性集合 /// </summary> /// <param name="stepName">要筛选的步骤名称</param> /// <returns>对应步骤下的属性集合</returns> /// <exception cref="ArgumentNullException">当stepName为空时抛出</exception> public static IEnumerable<PropertyInfo> GetPropertiesByStepName(string stepName) { if (string.IsNullOrWhiteSpace(stepName)) throw new ArgumentNullException(nameof(stepName), "步骤名称不能为空"); return GetAllStepProperties() .Where(prop => { var stepAttr = prop.GetCustomAttribute<StepAttribute>(); // 这里用忽略大小写的比较,你可以根据需求改成精确匹配 return stepAttr != null && stepAttr.StepName.Equals(stepName, StringComparison.OrdinalIgnoreCase); }) .ToList(); } }
3. 使用示例
针对你的MobileKeyViewData模型,这样调用即可:
// 获取所有带StepAttribute的属性 var allStepProperties = StepPropertyHelper<MobileKeyViewData>.GetAllStepProperties(); foreach (var prop in allStepProperties) { var stepAttr = prop.GetCustomAttribute<StepAttribute>(); Console.WriteLine($"属性:{prop.Name},类型:{prop.PropertyType.Name},所属步骤:{stepAttr.StepName}"); } // 获取"PersonalData"步骤下的属性 var personalDataProps = StepPropertyHelper<MobileKeyViewData>.GetPropertiesByStepName("PersonalData"); foreach (var prop in personalDataProps) { Console.WriteLine($"PersonalData步骤的属性:{prop.Name}"); }
4. 进阶:返回封装后的属性信息(可选)
如果需要更友好的返回结果,可以创建一个DTO类来封装属性的关键信息:
public class StepPropertyDetail { public string PropertyName { get; set; } public Type PropertyType { get; set; } public string StepName { get; set; } }
然后修改泛型类的方法,返回这个DTO集合:
public static IEnumerable<StepPropertyDetail> GetAllStepPropertyDetails() { var modelType = typeof(T); return modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(prop => Attribute.IsDefined(prop, typeof(StepAttribute))) .Select(prop => new StepPropertyDetail { PropertyName = prop.Name, PropertyType = prop.PropertyType, StepName = prop.GetCustomAttribute<StepAttribute>().StepName }) .ToList(); }
这样调用时就能直接拿到结构化的信息,不用再手动获取属性特性了。
内容的提问来源于stack exchange,提问作者Fabio Santos
相关产品推荐
相关产品推荐

