提问人:Christopher Fontaine 提问时间:11/10/2023 最后编辑:Christopher Fontaine 更新时间:11/10/2023 访问量:76
比较在 C# 中通过静态泛型类和使用 ConcurrentDictionary 访问静态类的特征
Comparing characteristics of accessing class properties in C# via a static generic class and static class with ConcurrentDictionary
问:
我使用的是 C#,我有两种访问类属性的方法:through 和 .这两个选项都提供对类元数据的访问,以便使用属性。我对它们在性能、内存使用、线程安全和其他相关方面的差异很感兴趣。Entity<Unit>.PropertyAccessors
EntityManager.PropertyAccessor<Unit>()
在性能、内存使用、线程安全和其他关键方面,它们之间的主要区别是什么?这些类别中是否有首选选项?在使用这些实现时,我是否应该注意任何潜在的陷阱或陷阱?Entity<Unit>.PropertyAccessors
EntityManager.PropertyAccessor<Unit>()
我正在使用引擎盖下的 ThreadSafeDictionary。ConcurrentDictionary<TKey, Lazy<TValue>>
以下是我用于更详细上下文的代码:
using System.Reflection;
using System.Linq.Expressions;
internal sealed record PropertyAccessor(string Name, Func<object, object> Get, Action<object, object> Set);
internal static class Entity<TEntity> where TEntity : class, IEntity
{
public static IEnumerable<PropertyAccessor> PropertyAccessors => LazyPropertyAccessors.Value;
private static readonly Lazy<IList<PropertyAccessor>> LazyPropertyAccessors = new(() => GetPropertiesAccessor(typeof(TEntity)));
private static IList<PropertyAccessor> GetPropertiesAccessor(IReflect type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && p.CanWrite)
.Select(GetEntityProperty)
.ToArray();
}
private static PropertyAccessor GetEntityProperty(PropertyInfo property)
{
return new PropertyAccessor(property.Name, property.GetGetMethod().BuildGetAccessor(), property.GetSetMethod().BuildSetAccessor());
}
}
internal static class EntityManager
{
private static readonly IThreadSafeDictionary<Type, IEnumerable<PropertyAccessor>> EntitiesPropertiesAccessor;
static EntityManager()
{
EntitiesPropertiesAccessor = new ThreadSafeDictionary<Type, IEnumerable<PropertyAccessor>>();
}
public static IEnumerable<PropertyAccessor> PropertiesAccessor<TEntity>() where TEntity : class, IEntity
{
return EntitiesPropertiesAccessor.GetOrAdd(typeof(TEntity), GetPropertiesAccessor);
}
private static IEnumerable<PropertyAccessor> GetPropertiesAccessor(IReflect type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && p.CanWrite)
.Select(GetEntityProperty)
.ToArray();
}
private static PropertyAccessor GetEntityProperty(PropertyInfo property)
{
return new PropertyAccessor(property.Name, property.GetGetMethod().BuildGetAccessor(), property.GetSetMethod().BuildSetAccessor());
}
}
public static class ReflectionTypeExtensions
{
public static Func<object, object> BuildGetAccessor(this MethodInfo method)
{
if (method == null)
throw new ArgumentNullException(nameof(method));
var declaringType = method.DeclaringType;
if (declaringType == null)
throw new NullReferenceException(nameof(method.DeclaringType));
var obj = Expression.Parameter(typeof(object));
var getter = Expression.Lambda<Func<object, object>>(
Expression.Convert(Expression.Call(Expression.Convert(obj, declaringType), method), typeof(object)),
obj);
return getter.Compile();
}
public static Action<object, object> BuildSetAccessor(this MethodInfo method)
{
if (method == null)
throw new ArgumentNullException(nameof(method));
var declaringType = method.DeclaringType;
if (declaringType == null)
throw new NullReferenceException(nameof(method.DeclaringType));
var obj = Expression.Parameter(typeof(object));
var value = Expression.Parameter(typeof(object));
var expr = Expression.Lambda<Action<object, object>>(Expression.Call(Expression.Convert(obj, declaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj,
value);
return expr.Compile();
}
}
附加信息:
- 我还没有尝试过 BenchmarkDotNet。
- 我对如何处理静态共享类的内存分配很感兴趣。与具有静态 ConcurrentDictionary 的静态类相比,此方法是否具有优势?
IEntity
只是数据库中实体模型的标签
这是他的代码:
public interface IEntity
{
long Id { get; set; }
}
Unit
只是数据库中没有逻辑且仅由属性组成的实体模型
这是他的代码:
public class Unit : IEntity
{
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
- 此代码旨在获取实体模型的所有属性,以便以后可以实现复制。添加了 static、Lazy 和 ConcurrentDictionary 机制,以避免每次都对相同的类型使用反射和表达式树。
因此,我将缩短我的问题,如何处理静态泛型类的内存处理?在这种情况下,使用静态缓冲区的一个静态类会更有优势吗?使用静态泛型类时,是否应注意任何潜在的陷阱或问题?
答: 暂无答案
评论