C#特性和反射的应用(一)
之前的项目使用了一个轻量级的开源ORM框架Fluentdata,因为项目中领域模型和实体模型合在一起,添加数据时就会出现因为实体和数据库表对应有差异而不能直接保存(某些实体的属性在数据库表里没有对应的字段)。通过查看Fluentdata的源代码,发现可以给实体里面无法对应数据库表字段的属性添加一个自定义特性,然后修改Fluentdata源代码,通过反射,把这些属性“屏蔽”。
首先新建一个自定义特性类DbFieldAttribute,代码如下:
[AttributeUsage(AttributeTargets.Property)] public class DbFieldAttribute : Attribute { public DbFieldAttribute() { } public DbFieldAttribute(bool isDbField) { _isDbField = isDbField; } private bool _isDbField; public virtual bool IsDbField { get { return _isDbField; } set { _isDbField = value; } } }
DbFieldAttribute自定义特性类创建好之后在实体属性上面加上这个自定义特性
/// <summary> /// 操作员单位 /// </summary> [Description("操作员单位")] public string RIA100 { get; set; } /// <summary> /// 附件路径1 /// </summary> [DbField(false)] public string att01 { get; set; } /// <summary> /// 附件路径2 /// </summary> [DbField(false)] public string att02 { get; set; }
自定义的特性类使用的时候可以把类名里的Attribute省略到。
[DbField(false)]
然后修改Fluentdata源代码如下
internal void AutoMapColumnsAction<T>(params Expression<Func<T, object>>[] ignorePropertyExpressions) { var properties = ReflectionHelper.GetProperties(_data.Item.GetType()); var ignorePropertyNames = new HashSet<string>(); if (ignorePropertyExpressions != null) { foreach (var ignorePropertyExpression in ignorePropertyExpressions) { var ignorePropertyName = new PropertyExpressionParser<T>(_data.Item, ignorePropertyExpression).Name; ignorePropertyNames.Add(ignorePropertyName); } } foreach (var property in properties) { var ignoreProperty = ignorePropertyNames.SingleOrDefault(x => x.Equals(property.Value.Name, StringComparison.CurrentCultureIgnoreCase)); if (ignoreProperty != null) continue; /********************Start*******Author:suxiaobo Date:2013-10-08***********************************/ //根据特性标识来判断实体属性是不是数据库表里面的字段 int i = property.Value.GetCustomAttributes(true).OfType<DbFieldAttribute>().Count(atr => !(atr).IsDbField); if (i > 0) continue; /********************End*******Author:suxiaobo Date:2013-10-08***********************************/ var propertyType = ReflectionHelper.GetPropertyType(property.Value); var propertyValue = ReflectionHelper.GetPropertyValue(_data.Item, property.Value); ColumnAction(property.Value.Name, propertyValue, propertyType, DataTypes.Object, 0); } }
这里GetCustomAttributes方法是返回一个包含所有自定义特性的数组,然后判断这个属性是否包含DbFieldAttribute自定义特性,并且IsDbField的值为false。
上面就是项目中的一个自定义特性和反射结合的应用,因本人水平有限有什么错误的地方欢迎大家指出。