将C#Covert类型转换为相同类型的IEnumerable? [英] C# Covert Type into IEnumerable of same Type?
问题描述
我有一些方法可以对数据库执行任意SQL,并将该数据集合序列化为具体类型的列表。然后将该数据序列化为JSON并存储在表的单元格中。后来,我需要返回并将这些数据反序列化为原始数据集,以便可以使用它。
I have some methods that execute arbitrary SQL against a database and serialize that data collection into a list of a concrete type. That data is then serialized into JSON and stored in a cell in a table. Later, I need to come back and deserialize that data back into its original collection so that it can be used.
我遇到了一些问题,需要弄清楚如何获取 Type
对象并创建该类型的集合以反序列化它。这是我的代码的运行方式:
I'm having some issues figuring out how to take a Type
object and create a collection of that type in order to deserialize it. Here is how my code operates:
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>
才能正确反序列化。
Now when the ExecuteWidget
method is called, the type
parameter is populated by the widget's DTO datatype. For example HeadlineWidgetDTO
. However, the execute command gets the data back as a List<HeadlineWidgetDTO>
. When my FetchWidgetData
method is called, the dataType
supplied is still HeadlineWidgetDTO
, but it actually needs to be of type IEnumerable<HeadlineWidgetDTO>
to deserialize properly.
仅给出单个数据行的类型,我如何创建 Type
对象,而是一个集合
Given just the type for an individual data row, how can I create a Type
object that is instead a collection of that type?
推荐答案
这主要是如何使用激活器创建通用类型的实例并将其强制转换,但是很难说。
This is mostly a duplicate of How to use Activator to create an instance of a generic Type and casting it back to that type?, however it's hard to tell.
基本上,如果您有类型对象键入theType
,则需要执行以下操作:
Basically, if you have a type object Type theType
, you need to do something like:
var listType = typeof(List<>);
var typeParams = new [] {theType};
var listOfTType = listType.MakeGenericType(typeParams);
var newListOfT = Activator.CreateInstance(listOfTType);
此时,您有一个 object $ c类型的变量$ c>,但这引用了类型
List< WhateverYourTypeIs>
的对象。假设 theType
是 typeof(int)
,那么您将拥有 List<的对象。 int>
。但是,将其强制转换为可用的东西是另一个问题。如果您想在列表中添加一些内容,我怀疑最好的方法是为添加
获取 MethodInfo
方法和调用
它。
At that point, you have a variable of type object
, but that references an object of type List<WhateverYourTypeIs>
. Say, theType
is typeof(int)
, then you will have an object of List<int>
. Casting it to something usuable is a whole other question though. If you want to add something to that list, I suspect the best way would be to get a MethodInfo
for the Add
method and Invoke
it.
我想到了另一种方法,如果类型具有默认构造函数并且不是创建起来并不太昂贵。这是一个示例(创建 List< int>
-但这只是我的编码方式):
I thought of another way to do this if the type has a default constructor and isn't too expensive to create. Here's a sample (creating a List<int>
- but that's just the way I have it coded):
var type = typeof(int);
var dummy = Activator.CreateInstance(type);
var listOfType = new[] {dummy}.ToList();
完成后, listOfType
变量类型为 List< object>
,但引用 List< int>
。它大部分都可以使用-例如,您可以在其上调用 Add(object someObj)
。您不会进行编译类型参数类型检查,但是可以使用它。
When you are finished, the listOfType
variable is typed as a List<object>
but refers to a List<int>
. It's mostly mostly workable - for example, you can call Add(object someObj)
on it. You won't get compile type parameter type checking, but you will be able to use it.
这篇关于将C#Covert类型转换为相同类型的IEnumerable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!