[英]Are there libraries that convert from Expression trees or CodeDOM to Reflection.Emit?
[英]Switching from Reflection to Expression trees
由於逐行反射相當昂貴,我一直在尋找構建和插入實體的更快的替代方案。 我做了一些關於這個主題的研究 ,並且還發現了一些性能比較 ,這似乎表明表達樹是要走的路。 我將如何重寫以下功能以利用此功能?
public static void InsertTable(IEnumerable<DataTable> chunkedTable)
{
Parallel.ForEach(
chunkedTable,
new ParallelOptions
{
MaxDegreeOfParallelism = Convert.ToInt32(ConfigurationManager.AppSettings["MaxThreads"])
},
chunk =>
{
Realty_Records_ProdEntities entities = null;
try
{
entities = new Realty_Records_ProdEntities();
entities.Configuration.AutoDetectChangesEnabled = false;
foreach (DataRow dr in chunk.Rows)
{
var parcelToInsert = new Parcel();
foreach (DataColumn c in dr.Table.Columns)
{
var propertyInfo = parcelToInsert.GetType()
.GetProperty(
c.ColumnName,
BindingFlags.SetProperty | BindingFlags.IgnoreCase
| BindingFlags.Public | BindingFlags.Instance);
propertyInfo?.SetValue(
parcelToInsert,
TaxDataFunction.ChangeType(
dr[c.ColumnName],
propertyInfo.PropertyType),
null);
}
entities.Parcels.Add(parcelToInsert);
}
entities.SaveChanges();
}
catch (Exception ex)
{
TaxDataError.AddTaxApplicationLog(
TaxDataConstant.CategoryError,
ex.Source,
ex.Message,
ex.StackTrace);
throw;
}
finally
{
entities?.Dispose();
}
});
}
編輯:
以下是我最終實施的解決方案:
private static readonly ConcurrentDictionary<SetterInfo, Action<object,object>> CachedSetters =
new ConcurrentDictionary<SetterInfo, Action<object, object>>();
private static readonly MethodInfo ChangeTypeMethod =
((Func<object, Type, object>) TaxDataFunction.ChangeType).Method;
private static void SetProperty(object obj, string name, object value)
{
if (obj == null)
return;
var key = new SetterInfo(obj.GetType(), name);
var setter = CachedSetters.GetOrAdd(key, CreateSetter);
setter(obj, value);
}
private static Action<object, object> CreateSetter(SetterInfo info)
{
var propertyInfo = info.Type.GetProperty(info.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
return (s, v) => { };
var objParameter = Expression.Parameter(typeof(object));
var valueParameter = Expression.Parameter(typeof(object));
var changeTypeCall = Expression.Call(ChangeTypeMethod, valueParameter, Expression.Constant(propertyInfo.PropertyType));
var objCast = Expression.Convert(objParameter, info.Type);
var valueCast = Expression.Convert(changeTypeCall, propertyInfo.PropertyType);
var property = Expression.Property(objCast, propertyInfo);
var assignment = Expression.Assign(property, valueCast);
var lambda = Expression.Lambda<Action<object, object>>(assignment, objParameter, valueParameter);
return lambda.Compile();
}
private struct SetterInfo
{
public Type Type { get; }
public string Name { get; }
public SetterInfo(Type type, string name)
{
Type = type;
Name = name;
}
}
static ConcurrentDictionary<string, Lazy<Action<object, object>>> CachedProperties =
new ConcurrentDictionary<string, Lazy<Action<object, object>>>();
static void SetProperty(object obj, string name, object value)
{
if(obj==null)
throw new ArgumentNullException("obj");
Type objType = obj.GetType();
string key = objType.FullName + ":" + name;
Action<object, object> f =
CachedProperties.GetOrAdd(key, k =>
new Lazy<Action<object,object>>(() => {
PropertyInfo prop = objType.GetProperty(name);
if(prop==null){
return (s,v) => {};
}
ParameterExpression pobj =
Expression.Parameter(typeof(object));
ParameterExpression pval =
Expression.Parameter(typeof(object));
Expression left = Expression.Property(
Expression.TypeAs( pobj, objType), prop);
Expression right = Expression.Convert(pval, prop.PropertyType);
return Expression
.Lambda<Action<object, object>>(
Expression.Assign(left,right), pobj, pval).Compile();
})).Value;
f(obj,value);
}
用法....
SetProperty(parcelToInsert, c.ColumnName, dr[c.ColumnName])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.