2016-02-08 19 views
2

我遇到了一个问题,我无法弄清楚如何解决它。C#和Reflection不能连续工作两次

我有一个类从数据库中获取数据,在这个类我有一个方法简单SELECT *这种方法被称为

List<T> All<T>(string tableName) 

,你必须指定你的资源希望从经典的SQL Reader和SQL读取指令,例如

All<User>("users") 

而且,抛开,该方法的核心是这个

public override List<T> All<T>(string resource) 
    { 
     List<T> result = new List<T>(); 
     using (MySqlConnection sqlConnection = new MySqlConnection(connectionString)) 
     { 
      sqlConnection.Open(); 
      try 
      { 
       string query = "SELECT * FROM " + resource + " WHERE 1=1"; 
       using (MySqlCommand sqlCommand = new MySqlCommand(query, sqlConnection)) 
       { 
        lock (locker) 
        { 
         MySqlDataReader reader = sqlCommand.ExecuteReader(); 
         if (reader.HasRows) 
         { 
          while (reader.Read()) 
          { 
           T model = Activator.CreateInstance<T>(); 
           Dictionary<string, object> _properties = new Dictionary<string, object>(); 
           for (int i = 0; i < reader.FieldCount; i++) 
           { 
            string property = reader.GetName(i); 
            object value = reader.GetValue(i); 
            _properties.Add(property, value); 
           } 
           var type = model.GetType(); 
           var method = type.GetMethod("SetProperties"); 
           var invoked = method.Invoke(model, new object[] { _properties }); 

           result.Add(model); 
          } 
         } 
         reader.Close(); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Program.eventLogger.Add(new Event(EventType.Error, "SQL Data Providers", "Exception catched on All", ex)); 
      } 
      finally 
      { 
       sqlConnection.Close(); 
      } 
     } 
     return result; 
    } 

基本上,基于来自方法头的类型,该方法将尝试创建特定类型的新实例,稍后对于查询中的每个字段,它将填充临时列表上的类的所有属性。一旦完成,它将尝试调用基本上使用反射设置类的每个属性的方法“SetProperties”。

这是setProperties方法的核心,等于为每个实体:

public virtual bool SetProperties(Dictionary<string,object> properties) 
    { 
     if(this.ValidateData(properties)) 
     { 
      FillNullableAttributes(properties); 
      // Iterate trough every key : value pairs in properties 
      foreach (KeyValuePair<string, object> kvp in properties) 
      { 
       if (this.data.Contains(kvp.Key)) 
       { 
        var property = this.GetType().GetProperty(kvp.Key); 
        PropertyInfo propertyInfo = this.GetType().GetProperty(kvp.Key); 
        // Set the current fetched key with the given value if !null 
        if (kvp.Value != null) 
        { 
         Type fetchedType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; 
         object safeConversion = (kvp.Value == null || kvp.Value == DBNull.Value) ? null : Convert.ChangeType(kvp.Value, fetchedType); 
         if (propertyInfo.CanWrite) 
         { 
          propertyInfo.SetValue(this, safeConversion, null); 
         } 
        } 
       } 
      } 
      return true; 
     } 
     return false; 
    } 

最后的结果,这是一个列表,将返回与特定的实体将拥有自己的BindingList填补。绑定列表,每个实体描述如下:

public static BindingList<Seller> items = new BindingList<Seller>(); 

此代码工作正常,即使有,因为我知道的改善有很大的空间,但如果我把它叫做两次这样的:

User.items = new BindingList<User>(provider.All<User>("users")); 
User.items = new BindingList<User>(provider.All<User>("users")); 

第二个列表将由空实体填充,计数将是正确的,但它们将是空的......并且不应该发生。

,我想通了,从调试的唯一的事情是,在第二次调用

var invoked = method.Invoke(model, new object[] { _properties }); 

调用设置为false。

+3

所以,我知道这并不回答你的问题,但为什么不强迫模型实现一个包含'SetProperties'方法的接口。这将是更多的表演。 – CodingGorilla

+1

读者是否正确地重新初始化,以便对Read()的调用返回数据? –

+0

@ErnodeWeerd是的,它关闭并正确打开每个SQL调用 –

回答

2

结果:

var invoked = method.Invoke(model, new object[] { _properties }); 

是从SetProperties方法,是否被调用的方法,你的问题表明的返回值。你的SetProperties方法告诉你,它无法完成它的工作,调试它,你会发现你的答案。

+1

顺便说一句 - 我仍然建议你实现一个接口。 :) – CodingGorilla

+0

我知道,这不是我必须接管的项目中的代码的一部分,这是结果 –

相关问题