gpt4 book ai didi

c# - System.Reflection 性能

转载 作者:行者123 更新时间:2023-12-03 18:36:18 24 4
gpt4 key购买 nike

我有一个数据库管理器,用于插入或添加到内部 SQLite 数据库以及读取。

对于回读,我使用这样的通用方法

 public List<T> GetListOfObjects<T>(string id) where T:IIdentity, new()
{
lock (dbLock)
{
using (var sqlCon = new SQLiteConnection(DBPath))
{
sqlCon.Execute(Constants.DBClauseSyncOff);
sqlCon.BeginTransaction();
string sql = string.Format("SELECT * FROM {0} WHERE id=\"{1}\"", GetName(typeof(T).ToString()), id);
var data = sqlCon.Query<T>(sql);
return data;
}
}
}

没什么了不起的,但我所有的读取方法大约有 130 行代码。

我的二传手虽然不同——几乎 1500 行涵盖了一大堆类。我想做的是使用系统反射合理化插入/更新方法,而不用担心插入的类,但允许反射为我做这件事。

从我读过的内容来看,这是完全可能的,因此我应该能够将代码压缩成类似于这个的东西
public void InsertOrUpdateClass<T>(List<T> obj) : where T:IIdentity, new()
{
foreach(var o in obj)
InsertOrUpdateClass(o);
}

public void InsertOrUpdateClass<T>(T o) : where T:IIdentity, new()
{
lock (dbLock)
{
using (var sqlcon = new SQLiteConnection(DBPath))
{
sqlcon.Execute(Constants.DBClauseSyncOff);
sqlcon.BeginTransaction();
try
{
// use reflection to construct the SQLite command line, insert
// into a string and pass into the query
if (sqlcon.Execute(SQLquery) == 0)
sqlcon.Insert(o, typeof(T));
sqlcon.Commit();
}
catch (Exception ex)
{
Console.WriteLine("Error in InsertOrUpdateClass : {0}", ex.Message);
sqlcon.Rollback();
}
}
}

但是,根据我的阅读,使用反射来执行此操作会比每个类更标准的单个插入或更新方法带来大约 x5 的性能损失。我见过的大多数示例表明,由于我没有使用任何讨厌的东西(例如 Activator.Create...),我的方法应该与“标准”代码一样快

这些类(因为它们用于数据库)具有不同的长度,并添加了 [Ignore] 和 [PrimaryKey] 的数据参数。如果反射会对这两者感到困惑,我还没有发现任何东西。

对此有任何建议将不胜感激。

最佳答案

使用表达式树的非常基本/幼稚的方法。您肯定需要为此做一些工作,具体取决于对象的复杂性,但这应该是一个很好的起点:

private readonly Dictionary<Type, Func<Object, String>> queryBuilders =
new Dictionary<Type, Func<object, string>>();

public String GetInsertQuery(Object entity)
{
var type = entity.GetType();
if (!queryBuilders.ContainsKey(type))
{
var param = Expression.Parameter(typeof(Object), "entity");
var typedObject = Expression.Variable(type, "obj");
var stringBuilder = Expression.Variable(typeof (StringBuilder), "sb");

var appendString = typeof (StringBuilder).GetMethod("Append", new[] {typeof (String)});
var objectToString = typeof(Object).GetMethod("ToString");

var code = new List<Expression>();
code.Add(Expression.Assign(typedObject, Expression.Convert(param, type)));
code.Add(Expression.Assign(stringBuilder, Expression.New(typeof (StringBuilder))));

code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(string.Format("INSERT INTO {0} (", type.Name))));

var properties = type.GetProperties();

for (int i = 0; i < properties.Length - 1; i++)
{
code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(properties[i].Name)));
code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(", ")));
}

code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(properties[properties.Length - 1].Name)));

code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(") VALUES (")));

for (int i = 0; i < properties.Length - 1; i++)
{
code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant("'")));
code.Add(Expression.Call(stringBuilder, appendString, Expression.Call(Expression.Property(typedObject, properties[i]), objectToString)));
code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant("', ")));
}

code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant("'")));
code.Add(Expression.Call(stringBuilder, appendString, Expression.Call(Expression.Property(typedObject, properties[properties.Length - 1]), objectToString)));
code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant("', ")));

code.Add(Expression.Call(stringBuilder, appendString, Expression.Constant(");")));


code.Add(Expression.Call(stringBuilder, "ToString", new Type[] { }));

var expression = Expression.Lambda<Func<Object, String>>(Expression.Block(new[] { typedObject, stringBuilder }, code), param);
queryBuilders[type] = expression.Compile();
}

return queryBuilders[type](entity);
}

尽管这也使用了反射,但主要区别在于反射只使用一次,并且对每种对象类型的进一步调用使用已编译的代码,因此不会对性能造成重大影响。主要缺点显然是复杂性——这种简单的方法远非万无一失和通用的,需要相当多的代码行——你肯定需要考虑减少代码库(以及潜在地提高可维护性)的好处是否值得付出代价(这也是可维护性——但你有一个相当复杂的方法,而不是成千上万的方法)。

关于c# - System.Reflection 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22532571/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com