چرا پیادهسازی Setter نسبت به Reflection الویت دارد؟
نویسنده: هادی مزارعی
تاریخ: ۱۴۰۴/۰۲/۲۲ ۱۶:۳۳
آدرس: www.dntips.ir
private List<(string ColumnName, Action<ImportModel, string> PropertySetter)>
CreatePropertyMappings(IEnumerable<MatchColumn> matchColumns)
{
// Pre-compile property setters for better performance
return matchColumns.Select(mc =>
{
var property = typeof(ImportModel).GetProperty(mc.PropertyName);
if (property == null)
throw new InvalidOperationException($"Property {mc.PropertyName} not found in ImportModel");
// Create a compiled setter action
Action<ImportModel, string> setter = (model, value) =>
{
try
{
property.SetValue(model, value);
}
catch (Exception ex)
{
throw new InvalidOperationException(
$"Error setting value '{value}' to property {mc.PropertyName}", ex);
}
};
return (mc.ColumnName, setter);
}).ToList();
}private List<(string ColumnName, Action<ImportModel, string> PropertySetter)> propertyMappings;
public void ProcessExcelRows(IEnumerable<Dictionary<string, string>> excelRows)
{
// یکبار نگاشتها را ایجاد میکنیم
propertyMappings = CreatePropertyMappings(matchColumns);
foreach (var row in excelRows)
{
var model = new ImportModel();
foreach (var mapping in propertyMappings)
{
if (row.TryGetValue(mapping.ColumnName, out var value))
{
mapping.PropertySetter(model, value); // استفاده از Setter بدون Reflection
}
}
// ذخیره مدل در دیتابیس یا پردازش بعدی
}
}private List<(string ColumnName, Action<ImportModel, string> PropertySetter)>
CreatePropertyMappings(IEnumerable<MatchColumn> matchColumns)
{
return matchColumns.Select(mc =>
{
var property = typeof(ImportModel).GetProperty(mc.PropertyName);
if (property == null)
throw new InvalidOperationException($"Property {mc.PropertyName} not found in ImportModel");
// ایجاد Expression Tree برای Setter
var modelParam = Expression.Parameter(typeof(ImportModel), "model");
var valueParam = Expression.Parameter(typeof(string), "value");
var assign = Expression.Assign(
Expression.Property(modelParam, property), // دسترسی مستقیم به Property
valueParam // مقدار ورودی
);
var lambda = Expression.Lambda<Action<ImportModel, string>>(assign, modelParam, valueParam);
var setter = lambda.Compile(); // کامپایل به کد اجرایی
return (mc.ColumnName, setter);
}).ToList();
}