我有一些方法可以对数据库执行任意SQL,并将该数据集合序列化为具体类型的列表。然后将该数据序列化为JSON并存储在表的单元格中。稍后,我需要返回并将这些数据反序列化为原始数据集,以便可以使用它。
我在解决如何获取Type
对象并创建该类型的集合以便反序列化时遇到一些问题。这是我的代码的工作方式:
public async Task ExecuteWidget(Guid runGuid, string widgetName, Type type, string sql,
IEnumerable<SqlParameter> parameters)
{
var report = operationsContext.ReportRuns.FirstOrDefault(n => n.RunGuid == runGuid);
CheckReportStatus(report);
var param = parameters.ToList();
var result = edwContext.Database.SqlQuery(type, sql, param.ToArray<object>());
var query = result.GetQuery(param);
var data = await result.ToListAsync();
var widgetData = new ReportRunWidgetData()
{
ReportRunId = report?.ReportRunId ?? -1, // This should never be null.
WidgetName = widgetName,
WidgetData = new JavaScriptSerializer().Serialize(data),
Query = query
};
operationsContext.ReportRunWidgetDatas.Add(widgetData);
await operationsContext.SaveChangesAsync();
}
我的提取逻辑如下所示:
public object FetchWidgetData(Guid runGuid, string widgetName, Type dataType)
{
var data = operationsContext.ReportRuns
.Include("ReportRunWidgetDatas")
.FirstOrDefault(n => n.RunGuid == runGuid)?
.ReportRunWidgetDatas.FirstOrDefault(n => n.WidgetName == widgetName)?
.WidgetData;
if (data == null) return null;
var deserialized = new JavaScriptSerializer().Deserialize(data, dataType);
return deserialized;
}
现在,当调用ExecuteWidget
方法时,type
参数由窗口小部件的DTO数据类型填充。例如HeadlineWidgetDTO
。但是,execute命令以List<HeadlineWidgetDTO>
的形式返回数据。调用我的FetchWidgetData
方法时,提供的dataType
仍为HeadlineWidgetDTO
,但实际上必须为IEnumerable<HeadlineWidgetDTO>
类型才能正确反序列化。
仅给出单个数据行的类型,我如何创建Type
对象,而不是该类型的集合?
答案 0 :(得分:3)
这主要是How to use Activator to create an instance of a generic Type and casting it back to that type?的副本,但是很难分辨。
基本上,如果您有类型对象Type theType
,则需要执行以下操作:
var listType = typeof(List<>);
var typeParams = new [] {theType};
var listOfTType = listType.MakeGenericType(typeParams);
var newListOfT = Activator.CreateInstance(listOfTType);
到那时,您拥有类型object
的变量,但它引用了类型List<WhateverYourTypeIs>
的对象。假设theType
是typeof(int)
,那么您将得到一个对象List<int>
。但是,将其强制转换为可用的东西是另一个问题。如果您想向该列表中添加内容,我怀疑最好的方法是为MethodInfo
方法获得一个Add
,然后为Invoke
获得一个
如果该类型具有默认构造函数且创建起来不太昂贵,我想到了另一种方法。这是一个示例(创建List<int>
-但这只是我的编码方式):
var type = typeof(int);
var dummy = Activator.CreateInstance(type);
var listOfType = new[] {dummy}.ToList();
完成后,将listOfType
变量键入为List<object>
,但引用一个List<int>
。它大部分都可以使用-例如,您可以在其上调用Add(object someObj)
。您不会获得编译类型参数类型检查,但是可以使用它。