I have below function to send the log. And I used to have a reflection approach.(The commented code inside the function). I would like to optimize the reflection, after some investigation online, I ended with below solution and it still took me the same time. (20 secs for processing 100k log records). Can anyone help/guide me why?
public static class JsonHelper
{
private static readonly ConcurrentDictionary<Type, Func<object, object>> _delegateCache =
new ConcurrentDictionary<Type, Func<object, object>>();
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> _propertyCache =
new ConcurrentDictionary<Type, PropertyInfo[]>();
public static string ToJson(this object obj)
{
return JsonConvert.SerializeObject(obj);
}
/// <summary>
/// Create LogEventInfo object.
/// </summary>
/// <param name="data"></param>
/// <param name="message"></param>
/// <param name="ex"></param>
/// <returns></returns>
public static LogEventInfo ToLogEventInfo(this ILogItem data, string message, Exception ex = null)
{
var eventInfo = new LogEventInfo();
if (ex != null)
eventInfo.Exception = ex;
if (data != null)
{
data.EventMessage = message;
data.LogTime = TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.Utc);
data.LogId = Guid.NewGuid();
//var properties = data.GetType().GetProperties();
//foreach (var property in properties)
//{
// eventInfo.Properties[property.Name] = property.GetValue(data, null);
//}
//Cache the delegate with expression tree.
if (!_propertyCache.TryGetValue(data.GetType(), out var propertyInfo))
{
var properties = data.GetType().GetProperties();
var delegateProperties = new Func<object, object>[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
delegateProperties[i] = GenerateGetterLambda(properties[i]);
var propertyName = properties[i].Name;
var propertyValue = delegateProperties[i].Invoke(data);
_delegateCache.TryAdd(properties[i].PropertyType, delegateProperties[i]);
eventInfo.Properties[propertyName] = propertyValue;
}
_propertyCache.TryAdd(data.GetType(), properties);
}
else
{
var properties = propertyInfo;
var length = properties.Length;
for (var i= 0; i < length; i++)
{
if (_delegateCache.TryGetValue(properties[i].PropertyType, out var propertyDelegate))
{
eventInfo.Properties[properties[i].Name] = propertyDelegate.Invoke(data);
}
}
}
}
else
{
if (!string.IsNullOrEmpty(message))
eventInfo.Message = message;
}
return eventInfo;
}
/// <summary>
/// Combined with expression tree to futher improve the performance.
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
private static Func<object, object> GenerateGetterLambda(PropertyInfo property)
{
var expParameter = Expression.Parameter(typeof(object), "instance");
var expInstance = Expression.TypeAs(expParameter, property.DeclaringType);
var expProperty = Expression.Property(expInstance, property);
var expPropertyObj = Expression.Convert(expProperty, typeof(object));
return Expression.Lambda<Func<object, object>>(expPropertyObj, expParameter).Compile();
}
}
Aucun commentaire:
Enregistrer un commentaire