Closed mucahitimre closed 1 year ago
I think use expression and cache check result will be better.
I changed to
private IEnumerable<KeyValuePair<string, object>> BuildKeyValuePairsFromObject(object data, bool considerKeys = false)
{
var dictionary = new Dictionary<string, object>();
var props = CacheDictionaryProperties.GetOrAdd(data.GetType(), type =>
{
var propDatas = new List<PropertyData>();
foreach (var property in type.GetRuntimeProperties())
{
if (property.GetCustomAttribute(typeof(IgnoreAttribute)) != null)
{
continue;
}
var colAttr = property.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute;
var name = colAttr?.Name ?? property.Name;
var hasColAttr = colAttr != null;
var isKeyAttr = colAttr is KeyAttribute;
var propData = new PropertyData
{
HasColumnAttribute = hasColAttr,
IsKeyAttribute = isKeyAttr,
PropertyInfo = property,
Name = name,
};
propData.BuildGetter();
propDatas.Add(propData);
}
return propDatas.ToArray();
});
for (int i = 0; i < props.Length; i++)
{
var property = props[i];
var propertyValue = property.Getter(data);
dictionary.Add(property.Name, propertyValue);
if (considerKeys && property.HasColumnAttribute)
{
if (property.IsKeyAttribute)
{
this.Where(property.Name, propertyValue);
}
}
}
return dictionary;
}
private class PropertyData
{
public PropertyInfo PropertyInfo;
public string Name;
public bool HasColumnAttribute;
public bool IsKeyAttribute;
public Func<object,object> Getter;
public void BuildGetter()
{
var par1 = Expression.Parameter(typeof(object));
Getter = Expression.Lambda<Func<object, object>>(
Expression.Convert(
Expression.Property(
Expression.Convert(par1, PropertyInfo.DeclaringType),
PropertyInfo.Name),typeof(object)), par1).Compile();
}
}
In net6.0 Release
Test code here
var query = new Query();
var instance = new Installment();
query.BuildKeyValuePairsFromObject(instance);//JIT&Cache
var sw = Stopwatch.GetTimestamp();
for (int i = 0; i < 10000; i++)
{
query.BuildKeyValuePairsFromObject(instance);
}
var ed = Stopwatch.GetTimestamp();
Console.WriteLine(new TimeSpan(ed - sw));
I try to eliminate repeated operations.
00:00:00.0221297
(Before)
00:00:00.0023049
(After)
While examining the properties, getting property attributes every time was causing slowness in large and batch operations, I made it keep the property attributes where it holds the properties.
second call performange; Before: 00:00:00.0000734 After: 00:00:00.0000310