我遇到了一个问题,我无法弄清楚如何解决它。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调用 –