C# 系统反射性能

C# 系统反射性能,c#,sqlite,reflection,C#,Sqlite,Reflection,我有一个数据库管理器,用于插入或添加到内部SQLite数据库以及读取 对于回读,我使用这样的通用方法 public List<T> GetListOfObjects<T>(string id) where T:IIdentity, new() { lock (dbLock) { using (var sqlCon = new SQLiteConnection(DBPath)) {

我有一个数据库管理器,用于插入或添加到内部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;
            }
        }
    }
public List GetListOfObjects(字符串id),其中T:IIdentity,new()
{
锁(dbLock)
{
使用(var sqlCon=newsqliteconnection(DBPath))
{
Execute(Constants.DBClauseSyncOff);
sqlCon.BeginTransaction();
string sql=string.Format(“SELECT*FROM{0},其中id=\“{1}\”,GetName(typeof(T).ToString()),id);
var data=sqlCon.Query(sql);
返回数据;
}
}
}
没什么了不起的,但是我所有的read方法大约有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();
                }
            }
        }
public void InsertOrUpdateClass(List obj):其中T:IIdentity,new()
{
foreach(obj中的var o)
InsertOrUpdateClass(o);
}
public void InsertOrUpdateClass(TO):其中T:IIdentity,new()
{
锁(dbLock)
{
使用(var sqlcon=newsqliteconnection(DBPath))
{
Execute(Constants.DBClauseSyncOff);
sqlcon.BeginTransaction();
尝试
{
//使用反射构造SQLite命令行insert
//转换为字符串并传递到查询中
if(sqlcon.Execute(SQLquery)==0)
sqlcon.Insert(o,typeof(T));
提交();
}
捕获(例外情况除外)
{
WriteLine(“InsertOrUpdateClass:{0}中的错误”,例如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);
}
专用只读字典查询生成器=
新字典();
公共字符串GetInsertQuery(对象实体)
{
var type=entity.GetType();
如果(!queryBuilders.ContainsKey(类型))
{
var param=表达式参数(typeof(Object),“entity”);
var typedObject=Expression.Variable(类型“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.Add(Expression.Assign(typedObject,Expression.Convert(param,type)));
code.Add(Expression.Assign(stringBuilder,Expression.New)(typeof(stringBuilder)));
Add(Expression.Call(stringBuilder、appendString、Expression.Constant(string.Format(“插入到{0}(,type.Name))));
var properties=type.GetProperties();
对于(int i=0;i
虽然这也使用反射,但主要区别在于反射只使用一次,并且对每种对象类型的进一步调用都使用编译代码,因此没有显著的性能影响。主要缺点显然是复杂性-简单的方法,远远不是傻瓜式的和通用的,需要相当多的代码行-您肯定需要考虑到减少代码库(也可能提高可维护性)的好处是否值得花费(WHIC)。