【发布时间】:2016-11-14 15:44:23
【问题描述】:
我编写了一个泛型方法,它从数据表中生成泛型类型的集合。我已经寻找了不同的实现,但是在处理大量属性和大量记录时,它们中的大多数都表现得很糟糕。到目前为止,这个表现相当不错。
我尝试通过在属性顶部添加自定义属性 ( DataField ) 来改进该方法,这样我可以将其包含在属性中,我可以跳过将其与列匹配,或者为将匹配数据表的列名的属性。
我查看了代码,现在它看起来像一团糟,我真的不为它感到自豪,我希望有一个更好的实现。谁能给我一些提示?将不胜感激。
尝试将 cmets 包括在内,但不确定它有多大帮助。谢谢,代码如下:
private static void SetItemFromRow<T>(T item, DataRow row) where T : new()
{
// Get all properties with attributes.
PropertyInfo[] propWithAttributes = item.GetType().GetProperties().Where(x => Attribute.IsDefined
(x, typeof(DataField))).ToArray();
foreach (DataColumn col in row.Table.Columns)
{
// Find property that matches the column name.
PropertyInfo p = item.GetType().GetProperty(col.ColumnName);
bool ignoreProperty = false;
if (p != null)
{
// If no attribute exists set the property value. Break out from the loop to go to the next column (Property).
if (!propWithAttributes.Contains(p))
{
if (row[col] != DBNull.Value)
{
p.SetValue(item, row[col], null);
continue;
}
}
// If the property has a custom attribute then check if its ignore property is true. If so we break out from the loop and go to the next column (Property).
var attrs = p.GetCustomAttributes(typeof(DataField), false).ToArray() as DataField[]; ;
if (attrs != null)
foreach (var attr in attrs)
{
if (attr.Ignore)
ignoreProperty = true;
}
if (ignoreProperty) continue;
}
SetPropertyWithCustomName(item, propWithAttributes, row, col);
}
}
现在我们已经在具有匹配列名称的对象上设置了所有属性,并且我们跳过了所有我们想要忽略的属性。最后一步是设置具有定义了 Name 的 DataField 属性的属性。
private static void SetPropertyWithCustomName<T>(T item, PropertyInfo[] propWithAttributes, DataRow row, DataColumn col)
where T : new()
{
foreach (var prop in propWithAttributes)
{
// Get the attributes for the property.
var attrs = prop.GetCustomAttributes(typeof(DataField), false).ToArray() as DataField[];
bool match = false;
if (attrs != null)
{
foreach (var attr in attrs)
{
// Check if the column name matches the custom name on the property.
if (col.ColumnName == attr.Name)
{
var p = item.GetType().GetProperty(prop.Name);
if (row[col] != DBNull.Value)
{
p.SetValue(item, row[col], null);
match = true;
break;
}
}
}
if (match) break;
}
}
}
【问题讨论】:
-
定义 nicier?更容易阅读?快点?内存效率更高?无论如何,代码审查已经完成there。
-
现在更可读了。
-
谢谢,我会在“那里”试一试。
-
您至少应该缓存您对 GetProperty 的所有调用。您为每个数据行对 GetProperty 进行了许多相同的调用。此外,使用属性后缀 (DataFieldAttribute) 命名属性也是一种常见约定。
-
感谢您的提示。
标签: c# reflection custom-attributes