我正在尝试用Dapper和存储过程编写一些更通用的代码。我做了一些研究,但我被这部分卡住了…
我有一些类似实体的类,这些实体将被一些存储过程返回(那些过程不能被修改)。例如,我有两个类。
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
存储过程通常返回一些select子句,对于本例,它返回两个select子句,每个子句用于用户和角色的信息,因此我有以下类来存储这些子句。
public class UserAndRoleInfo
{
public IEnumerable<User> users { get; set; }
public IEnumerable<Role> roles { get; set;}
}
在这个项目中,我们必须使用Dapper,所以我做了一个泛型函数,其中T是将返回的类,这个类具有与上面显示的相同的结构,并且可以有两个或更多的实体作为属性。
其主要思想是获取T的属性,然后为每个属性获取由铸造为property type的select子句返回的值,最后将该属性添加到将要返回的类实例中。
public async Task<T> ExecuteStoreProcedureMultiQuery<T>(string cnx, string storeProcedure, object param = null) where T : class, new()
{
using (var conn = new SqlConnection(cnx))
{
conn.Open();
var result = param == null
? await conn.QueryMultipleAsync(
storeProcedure,
commandType: CommandType.StoredProcedure
).ConfigureAwait(false)
: await conn.QueryMultipleAsync(
storeProcedure,
param: param,
commandType: CommandType.StoredProcedure
).ConfigureAwait(false);
T res = new T();
Type t = typeof(T);
PropertyInfo[] propInfos = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach(PropertyInfo propInfo in propInfos){
// I want to do something like this
propInfo.PropertyType propValue = result.Read<propInfo.PropertyType.GetEnumUnderlyingType()>();
propInfo.SetValue(res, propValue);
}
conn.Close();
conn.Dispose();
return res;
}
}
这里的问题是,我不确定如何获得这个PropInfo.PropertyTypePropValue=Result.Read
,我正在使用Activator.CreateInstance(propInfo.PropertyType)
,但我不确定在这种情况下如何实现它。
如果有些东西不清楚或者需要更多的信息,我在这里回答。提前道谢。
使用这里的答案作为参考,您可以这样做:
foreach (var propInfo in propInfos)
{
var method = result.GetType().GetMethod(nameof(result.Read));
var generic = method.MakeGenericMethod(propInfo.PropertyType.GetEnumUnderlyingType());
var propValue = generic.Invoke(result, null);
propInfo.SetValue(res, propValue);
}