gpt4 book ai didi

c# - GetCustomAttributes 性能问题(表达式树是解决方案??)

转载 作者:行者123 更新时间:2023-11-30 21:03:24 41 4
gpt4 key购买 nike

我遇到了性能问题,因为我使用反射和 GetCustomAttributes 进行数据访问。性能分析器检测到它。我有这样的扩展方法:

public static class DataRowExtensions
{
/// <summary>
/// Maps DataRow objecto to entity T depending on the defined attributes.
/// </summary>
/// <typeparam name="T">Entity to map.</typeparam>
/// <param name="rowInstance">DataRow instance.</param>
/// <returns>Instance to created entity.</returns>
public static T MapRow<T>(this DataRow rowInstance) where T : class, new()
{
//Create T item
T instance = new T();

IEnumerable<PropertyInfo> properties = typeof(T).GetProperties();
MappingAttribute map;
DataColumn column;

foreach (PropertyInfo item in properties)
{
//check if custom attribute exist in this property
object[] definedAttributes = item.GetCustomAttributes(typeof(MappingAttribute), false);

// Tiene atributos
if (definedAttributes != null && definedAttributes.Length == 1)
{
//recover first attribute
map = definedAttributes.First() as MappingAttribute;

column = rowInstance.Table.Columns.OfType<DataColumn>()
.Where(c => c.ColumnName == map.ColumnName)
.SingleOrDefault();

if (column != null)
{
object dbValue = rowInstance[column.ColumnName];
object valueToSet = null;

if (dbValue == DBNull.Value)//if value is null
valueToSet = map.DefaultValue;
else
valueToSet = dbValue;

//Set value in property
setValue<T>(instance, item, valueToSet);
}
}
}

return instance;
}

/// <summary>
/// Set "item" property.
/// </summary>
/// <typeparam name="T">Return entity type</typeparam>
/// <param name="instance">T type instance</param>
/// <param name="item">Property name to return value</param>
/// <param name="valueToSet">Value to set to the property</param>
private static void setValue<T>(T instance, PropertyInfo item, object valueToSet) where T : class, new()
{
if (valueToSet == null)
{
CultureInfo ci = CultureInfo.InvariantCulture;

if (item.PropertyType.IsSubclassOf(typeof(System.ValueType)))
{
//if is a value type and is nullable
if (item.PropertyType.FullName.Contains("System.Nullable"))
{
item.SetValue(instance, null, BindingFlags.Public, null, null, ci);
}
else
{
item.SetValue(instance, Activator.CreateInstance(item.PropertyType, null), BindingFlags.Public, null, null, ci);
}
}
else //property type is reference type
{
item.SetValue(instance, null, BindingFlags.Public, null, null, ci);
}
}
else // set not null value
{
//if is a value type and is nullable
if (item.PropertyType.FullName.Contains("System.Nullable"))
{
item.SetValue(instance, Convert.ChangeType(valueToSet, Nullable.GetUnderlyingType(item.PropertyType)), null);
}
else
{
item.SetValue(instance, Convert.ChangeType(valueToSet, item.PropertyType), null);
}
}
}
}

本质上,我在这里所做的是将域实体与数据库字段进行映射,然后数据助手会自动攻击表。这些实体之一的示例是:

public class ComboBox
{
/// <summary>
/// Represents a ComboBox item.
/// </summary>
[Mapping("CODE", DefaultValue = 0, DBType = DbParametersTypes.Varchar2, IsKey = true, IdentifierFK = "")]
public string Code { get; set; }

/// <summary>
/// Represents Text.
/// </summary>
[Mapping("DESCRIPTION", DefaultValue = "", DBType = DbParametersTypes.Varchar2, IsKey = false, IdentifierFK = "")]
public string Description { get; set; }

}

以及我使用的属性类:

public sealed class MappingAttribute : Attribute
{
public string ColumnName { get; set; }

public object DefaultValue { get; set; }

public DbParametersTypes DBType { get; set; }

public bool IsKey { get; set; }

public string IdentifierFK { get; set; }

public bool IsParameter { get; set; }

public MappingAttribute(string columnName)
{
if (String.IsNullOrEmpty(columnName))
throw new ArgumentNullException("columnName");

ColumnName = columnName;
}
}

我读了here可能的改进可能是表达式树,但首先,我不是表达式树专家,其次,我必须用 .NET 3.5 解决这个问题......(在示例中使用 .NET 4 或 4.5。 ..)

¿建议?

提前致谢。

最佳答案

public static class DataRowExtensions
{
/// <summary>
/// Maps DataRow objecto to entity T depending on the defined attributes.
/// </summary>
/// <typeparam name="T">Entity to map.</typeparam>
/// <param name="rowInstance">DataRow instance.</param>
/// <returns>Instance to created entity.</returns>
public static T MapRow<T>( this DataRow rowInstance ) where T : class, new()
{
//Create T item
var instance = new T();
Mapper<T>.MapRow( instance, rowInstance );
return instance;
}

#region Nested type: Mapper

private static class Mapper<T>
where T : class
{
private static readonly ItemMapper[] __mappers;

static Mapper()
{
__mappers = typeof (T)
.GetProperties()
.Where( p => p.IsDefined( typeof (MappingAttribute), false ) )
.Select( p => new
{
Property = p,
Attribute = p
.GetCustomAttributes( typeof (MappingAttribute), false )
.Cast<MappingAttribute>()
.FirstOrDefault()
} )
.Select( m => new ItemMapper( m.Property, m.Attribute ) )
.ToArray();
}

public static void MapRow( T instance, DataRow row )
{
foreach ( var mapper in __mappers )
{
mapper.MapRow( instance, row );
}
}

#region Nested type: ItemMapper

private sealed class ItemMapper
{
private readonly MappingAttribute _attribute;
private readonly PropertyInfo _property;

public ItemMapper( PropertyInfo property, MappingAttribute attribute )
{
_property = property;
_attribute = attribute;
}

public void MapRow( T instance, DataRow rowInstance )
{
//TODO: Implement this with the code already provided
}
}

#endregion
}

#endregion
}

第一次为给定的 <T> 调用扩展方法,静态构造函数将运行并缓存一个实例 Mapper对于每个具有 MappingAttribute 的属性随附的。然后,对于此后的每次调用,它将使用缓存的映射器进行实际复制。

你也可以制作Mapper抽象,并为您的 setValue<T>() 中的每个分支使用不同的子类.这样,您的大部分反射(reflection)只会发生一次。

关于c# - GetCustomAttributes 性能问题(表达式树是解决方案??),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12914990/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com