将C#Covert类型转换为相同类型的IEnumerable? [英] C# Covert Type into IEnumerable of same Type?

查看:76
本文介绍了将C#Covert类型转换为相同类型的IEnumerable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些方法可以对数据库执行任意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 ,但这引用了类型 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆