我有以下方法:
private JobCard PopulateObject(JobCard jc, DataRow dataRow)
{
PropertyInfo[] proplist = jc.GetType().GetProperties();
foreach (PropertyInfo propertyitem in proplist)
{
if (propertyitem.Name != "")
if (propertyitem.PropertyType.BaseType.Namespace == "System")
{
propertyitem.SetValue(jc, dataRow[propertyitem.Name], null);
}
else
{
string typename = propertyitem.ToString().Replace("Pss.Common.Mia.", "");
int i = typename.IndexOf("Base");
typename = typename.Substring(0, i);
Type type = propertyitem.PropertyType;
switch (typename)
{
case "Customer":
propertyitem.SetValue(jc, PopulateCustomerObject(propertyitem, dataRow, type), null);
break;
case "Meter":
propertyitem.SetValue(jc, PopulateMeterObject(propertyitem, dataRow, type), null);
break;
case "TimeSheet":
propertyitem.SetValue(jc, PopulateTimeSheetObject(propertyitem, dataRow, type), null);
break;
}
}
}
return jc;
}
上述方法称为:
private Customer PopulateCustomerObject(object o, DataRow dataRow, Type type)
{
IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
Customer c = new Customer();
Guid customerGuid = new Guid(dataRow["AddressId"].ToString());
string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View;
string query = string.Format("select * from {0} where id = '{1}'", view, customerGuid);
c = DataAccess.Retriever.Retrieve<Customer>(query);
return c;
}
private Address PopulateAddressObject(object o, DataRow dataRow, Type type)
{
IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
Address a = new Address();
Guid AddressGuid = new Guid(dataRow["PhysicalAddressId"].ToString());
string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View;
string query = string.Format("select * from {0} where id = '{1}'", view, AddressGuid);
a = DataAccess.Retriever.Retrieve<Address>(query);
return a;
}
private Meter PopulateMeterObject(object o, DataRow dataRow, Type type)
{
IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
Meter m = new Meter();
Guid meterGuid = new Guid(dataRow["MeterId"].ToString());
string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View;
string query = string.Format("select * from {0} where id = '{1}'", view, meterGuid);
m = DataAccess.Retriever.Retrieve<Meter>(query);
return m;
}
我可以看到最好用1种通用方法代替,但是如何?
我没看到如何替换
Customer c = new Customer();
Address a = new Address();
Meter m = new Meter();
TimeSheet t = new TimeSheet();
有1个通用行,还有
c = DataAccess.Retriever.Retrieve<Customer>(query);
a = DataAccess.Retriever.Retrieve<Address>(query);
m = DataAccess.Retriever.Retrieve<Meter>(query);
t = DataAccess.Retriever.Retrieve<TimeSheet>(query);
我无法更改Retriever.Retrieve。它被声明为
public static T Retrieve<T>(string query)
where T : IDataStorable
{
return Retrieve<T>(query, new IDbDataParameter[0], string.Empty);
}
答案 0 :(得分:1)
这一切看起来有点模糊和复杂,但要直接回答你的问题 - 为了使PopulateAddressObject函数具有通用性,你可以这样做:
private TPopulateAddressObject(object o, DataRow dataRow, Type type, string idColumnName) where T : IDataStorable, new()
{
IDataStorable instance = (IDataStorable)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
PropertyInfo[] proplist = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
T obj = new T();
Guid id = new Guid(dataRow[idColumnName].ToString());
string view = ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(type).View;
string query = string.Format("select * from {0} where id = '{1}'", view, id);
obj = DataAccess.Retriever.Retrieve<T>(query);
return obj;
}
答案 1 :(得分:1)
Populate*
方法中有很多东西你不使用;例如,你实际上并没有使用你花费大量时间创建的对象......
如何将PrimaryKey
属性添加到[DBObjectRetrieveAttribute]
(以保存已映射的DataRow
列),如下所示:
private static T Populate<T>(DataRow dataRow)
where T : class, IDataStorable, new()
{
DBObjectRetrieveAttribute ora =
ReflectionHelper.GetAttribute<DBObjectRetrieveAttribute>(typeof(T));
string view = ora.View;
Guid pkid = new Guid(dataRow[ora.PrimaryKey].ToString());
// beware SQL injection...
string query = string.Format("select * from {0} where id = '{1}'",
view, pkid);
return DataAccess.Retriever.Retrieve<T>(query);
}
然后就不需要打开不同的属性类型了;你可以使用MakeGenericMethod
:
object obj = MethodInfo mtd = typeof(SomeType).GetMethod("Populate",
BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(propertyitem.PropertyType)
.Invoke(null, new object[] {dataRow});
propertyitem.SetValue(jc, obj, null);
可替换地;将id作为参数传递:
private static T Populate<T>(DataRow dataRow, string primaryKey)
where T : class, IDataStorable, new()
{
... snip
Guid pkid = new Guid(dataRow[primaryKey].ToString());
... snip
}
做类似的事情:
object obj;
if(type == typeof(Customer)) {
obj = Populate<Customer>(dataRow, "AddressId");
} else if (type == typeof(Meter)) {
obj = Populate<Meter>(dataRow, "MeterId");
} else if (...etc...) {
} else {
throw new InvalidOperationException("Type is not supported: " + type.Name);
}
propertyitem.SetValue(jc, obj, null);