2016-02-08 27 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

我知道,這不是我必須接管的項目中的代碼的一部分,這是結果 –

相關問題