我遇到了一個問題,我無法弄清楚如何解決它。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。
所以,我知道這並不回答你的問題,但爲什麼不強迫模型實現一個包含'SetProperties'方法的接口。這將是更多的表演。 – CodingGorilla
讀者是否正確地重新初始化,以便對Read()的調用返回數據? –
@ErnodeWeerd是的,它關閉並正確打開每個SQL調用 –