如何将propertyInfo.PropertyType作为数据类型传递以实例化变量并将其传递给泛型函数?

How could I pass a propertyInfo.PropertyType as an Datatype to instanciate a variable and pass it to a generic function?

提问人:Héctor Marin 提问时间:4/28/2021 最后编辑:Amit JoshiHéctor Marin 更新时间:6/22/2021 访问量:230

问:

我正在尝试使用 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 子句,每个子句用于 User 和 Role 的信息,因此我有以下类来存储这些子句。

public class UserAndRoleInfo 
{
     public IEnumerable<User> users { get; set; }
     public IEnumerable<Role> roles { get; set;}
}

在这个项目中,我们必须使用 Dapper,所以我正在做一个泛型函数,其中 T 是将要返回的类,这个类具有与上面所示相同的结构,并且可以有两个或多个实体作为属性。

主要思想是获取 T 的属性,然后为每个属性获取 select 子句返回的值,该子句转换为属性类型,最后将此属性添加到将返回的类实例中。

public async Task<T> ExecuteStoredProcedureMultiQuery<T>(string cnx, string storedProcedure, object param = null) where T : class, new()
{
     using (var conn = new SqlConnection(cnx))
     {
         conn.Open();
         var result = param == null
                ? await conn.QueryMultipleAsync(
                    storedProcedure,
                    commandType: CommandType.StoredProcedure
                ).ConfigureAwait(false)
                : await conn.QueryMultipleAsync(
                    storedProcedure,
                    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.PropertyType propValue = result.Read<propInfo.PropertyType.GetEnumUnderlyingType()>();

我正在使用 ,但我不确定在这种情况下如何实现它。Activator.CreateInstance(propInfo.PropertyType)

如果有什么不清楚的地方或需要更多信息,我会在这里回答。提前致谢。

C# NET System.Reflection 属性信息

评论

2赞 Johnathan Barclay 4/28/2021
这回答了你的问题吗?如何使用反射来调用泛型方法?
0赞 Héctor Marin 4/28/2021
@JohnathanBarclay 你能告诉我在这种情况下如何应用它吗?
0赞 Connor Low 4/28/2021
他之所以这么说,是因为你在“类似的东西”代码中显示了,这是你无法做到的,并且链接的问题解决了。result.Read<propInfo.PropertyType.GetEnumUnderlyingType()>
0赞 Héctor Marin 4/28/2021
@ConnorLow,没错,我只是想知道在这种情况下我怎样才能做到这一点。因为我无法弄清楚如何让它工作
0赞 Connor Low 4/28/2021
将此答案应用于 。入手result.Readresult.GetType().GetMethod(nameof(result.Read)); ....

答:

0赞 Johnathan Barclay 4/28/2021 #1

使用此处的答案作为参考,您可以这样做:

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);
}