用DataRow参数递归调用泛型函数——MakeGenericMethod失败
本文关键字:函数 MakeGenericMethod 失败 泛型 调用 DataRow 参数 递归 | 更新日期: 2023-09-27 18:02:26
问题是:如果我有MyConvertDataRowToEntity(DataRow row)和我调用T对象从类型Parent和内部我调用相同的函数与子类型Child我该如何传递DataRow参数?这个问题是在调用MakeGenericMethod的Invoke时产生的。将类型更改为DataSet, string和string类型。没有运气。(我在列名中识别子对象但前缀- prefixdataccolumn)
public static T MyConvertDataRowToEntity<T>(DataRow row ) where T : class, new()
{
Type objType = typeof(T);
Type parentObjType = typeof(T);
T obj = Activator.CreateInstance<T>(); //hence the new() contsraint
PropertyInfo propertyGenericType = null;
object childInstance = null;
PropertyInfo property;
string childColumnName = string.Empty ;
foreach (DataColumn column in row.Table.Columns)
{
column.ColumnName = column.ColumnName.Replace("_", "");
string PrefixDataColumn;
if (column.ColumnName.IndexOf(".") > (-1))
{
///gets the prefix that is the same as child entity name
PrefixDataColumn = column.ColumnName.Substring(0, column.ColumnName.IndexOf("."));
///the column name in the child
int length = column.ColumnName.Length - 1;
int start = column.ColumnName.IndexOf(".") + 1;
childColumnName = column.ColumnName.Substring(column.ColumnName.IndexOf(".") + 1);
propertyGenericType = objType.GetProperty(PrefixDataColumn,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy);
parentObjType = objType;
if (propertyGenericType != null)
{
Type childType = propertyGenericType.PropertyType;
objType = childType;
childInstance = Activator.CreateInstance(propertyGenericType.PropertyType);
// get the get method for the property
MethodInfo method = propertyGenericType.GetGetMethod(true);
// get the generic get-method generator
MethodInfo genericHelper = typeof(DataUtil).GetMethod("MyConvertDataRowToEntity", BindingFlags.Public | BindingFlags.Static);
List<Type> signature = new List<Type>();
// first type parameter is type of target object
signature.Add(childType);
//next parameters are real types of method arguments
foreach (ParameterInfo pi in genericHelper.GetParameters())
{
signature.Add(pi.ParameterType);
}
// last parameters are known types of method arguments
signature.AddRange(typeof(T).GetGenericArguments());
// reflection call to the generic get-method generator to generate the type arguments
//MethodInfo constructedHelper = genericHelper.MakeGenericMethod(signature.ToArray());
// reflection call to the generic get-method generator to generate the type arguments
MethodInfo constructedHelper = genericHelper.MakeGenericMethod(childType );
// now call it. The null argument is because it's a static method.
object ret = constructedHelper.Invoke(null, new object[] { method });
// object myObj = method.Invoke(null, row);
//// property.SetValue(obj, MyConvertDataRowToEntity<childInstance>(DataRow row),null);
// childInstance = DataUtil.GetMethod("MyConvertDataRowToEntity").MakeGenericMethod(childType); //MyConvertDataRowToEntity<object>(row);
//childType initializedChild = ;
//property.SetValue(obj, value, null);
//objType = parentObjType;
}
else
{
continue;
}
}
}
return obj;
}
得到这个错误:System.Reflection类型的对象。RuntimeMethodInfo'不能转换为'System.Data.DataRow'类型。
有解决办法吗?
注。尽可能缩小代码范围。
如何使用继承类型递归地调用方法并传递数据流?
错误的原因是因为您正在调用MyConvertDataRowToEntity<ChildType>
,但随后将属性的getaccessor方法作为参数传递,而不是仅包含这些字段的数据行。
如果您想继续使用当前使用的代码处理逻辑,则需要构造一个新的数据流,其中包含从列名开头删除的所需字段(带有前缀和"。")。
或者,您可以创建一个助手方法,接受一个列名,源对象,它只是更新值。
static void UpdateItemProperty<T>(T item, string columnName, object rowValue) {
var prefixColumn=columnName.IndexOf(".")==-1 ? columnName : columnName.Split(".")[0];
var pi = typeof(T).GetProperty(prefixColumn // Add your binding flags);
// if pi==null then there is an error...
if (column.ColumnName.IndexOf(".") == (-1)) { // No Nesting
pi.SetValue(item,rowValue);
return;
}
// Nesting
var child=pi.GetValue(item);
if (child==null) {
// Logic here to get childs type and create an instance then call pi.SetValue with child
}
var remainder=string.Join(',',columnName.Split(".").Skip(1).ToArray());
// make your generic method info for UpdateItemProperty with pi.PropertyType into mi
mi.Invoke(null,new object[] { child,remainder,value };
}