我试图在运行时动态传递类的类型。下面的代码给出了代码段的错误:
object newObject Activator.CreateInstance(Type.GetType(t.GetGenericArguments()[0].FullName));
data.Read<newObject>();
我也试过
data.Read<Type.GetType(t.GetGenericArguments()[0].FullName)>();
下面是完整的方法:
public object FetchMultipleRecordSet(string storedProcedure, IList<QueryParameter> parameterCollection, object dataList)
{
if (!string.IsNullOrEmpty(storedProcedure))
{
using (SqlConnection sql = CreateDatabaseConnection())
{
DynamicParameters dynamicParameter = ConvertToDynamicParameters(parameterCollection);
var data = sql.QueryMultiple(storedProcedure, dynamicParameter, null, null, commandType: CommandType.StoredProcedure);
PropertyInfo[] properties = dataList.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
Type t = property.PropertyType;
if (t.BaseType == null && t.IsGenericType && t.Namespace == "System.Collection.Generic")
{
//property.SetValue(data.Read());
object newObject = Activator.CreateInstance(Type.GetType(t.GetGenericArguments()[0].FullName));
data.Read<>();
}
else if (t.Namespace != "System")
{
//typeCollection.Add(Type.GetType(t.FullName));
}
}
}
}
return dataList;
}
这是我想使用的视图模型:
public class ResultCollection
{
public IList<ShortCodeList> ShortCodeListCollection { get; set; }
public DateTime CurrentDate { get; set; }
public UserMembershipPlan UserMembershipPlanRecord { get; set; }
public IList<EmailRecipients> EmailRecipientsCollection { get; set; }
}
我需要将类型传递给data.Read(),以便可以将泛型形式的属性映射到结果集。如果我传递"newObject"或"Type.GetType(t.GetGenericArguments()[0]. fullname)",它仍然会给我错误。这可能看起来笨拙,但我认为它应该工作。
目前,dapper的类型化API使用泛型。有一个未类型化的API,但您需要自己进行成员映射。要通过类型调用泛型方法,需要在泛型方法上使用MethodInfo、MakeGenericMethod和Invoke。还有一种方法可以通过dynamic
欺骗它,通过在代码中添加shim方法,类似于:
dynamic template = ... // activator etc
Evil(template, otherArgs...);
Evil<T>(T template, otherArgs...) {
use some <T> method etc here
}
作为一个更完整的例子,如下所示:
public void TypeBasedViaDynamic()
{
Type type = GetSomeType();
dynamic template = Activator.CreateInstance(type);
dynamic actual = CheetViaDynamic(template,
"select @A as [A], @B as [B]", new { A = 123, B = "abc" });
((object)actual).GetType().IsEqualTo(type);
int a = actual.A;
string b = actual.B;
a.IsEqualTo(123);
b.IsEqualTo("abc");
}
T CheetViaDynamic<T>(T template, string query, object args)
{
return connection.Query<T>(query, args).SingleOrDefault();
}
static Type GetSomeType()
{
return typeof(SomeType);
}
public class SomeType
{
public int A { get;set; }
public string B { get;set; }
}
注意,这只是从一个Type
开始,并通过一个虚拟实例(通过Activator
)和dynamic
填充一个实例。不是很漂亮,但很有效。但是,我也刚刚对dapper进行了一些更改,使其接受Type
实例作为参数,从而使以下内容也可以工作,而不需要这些hack:
public void TypeBasedViaType()
{
Type type = GetSomeType();
dynamic actual = connection.Query(type,
"select @A as [A], @B as [B]", new { A = 123, B = "abc" }
).FirstOrDefault();
((object)actual).GetType().IsEqualTo(type);
int a = actual.A;
string b = actual.B;
a.IsEqualTo(123);
b.IsEqualTo("abc");
}
和多网格阅读器:
public void TypeBasedViaTypeMulti()
{
Type type = GetSomeType();
dynamic first, second;
using(var multi = connection.QueryMultiple(
"select @A as [A], @B as [B]; select @C as [A], @D as [B]",
new { A = 123, B = "abc", C = 456, D = "def" }))
{
first = multi.Read(type).Single();
second = multi.Read(type).Single();
}
((object)first).GetType().IsEqualTo(type);
int a = first.A;
string b = first.B;
a.IsEqualTo(123);
b.IsEqualTo("abc");
((object)second).GetType().IsEqualTo(type);
a = second.A;
b = second.B;
a.IsEqualTo(456);
b.IsEqualTo("def");
}
请注意,这些新API示例中的dynamic
纯粹是为了方便测试;dynamic
不是该方法的重要组成部分。