将对象显式强制转换为 C# 中仅在运行时可用的泛型类型的另一个对象

本文关键字:运行时 泛型类型 一个对象 对象 转换 | 更新日期: 2023-09-27 18:36:56

我正在尝试将某种类型转换为另一种泛型类型,但我找不到任何解决方案来说明在我的特定情况下如何做到这一点。简化情况如下。请注意,这可能看起来很奇怪和人为,但这只是为了指出我的问题。实际的应用程序更有意义... :-)

// Raw data coming from some source
public class RawDataType { }    
// Abstract base class for structured data representing this raw data
public abstract class AbstractListDataType { }
// Generates lists of structured data
public class ListGenerator<TListDataType> where TListDataType : AbstractListDataType
{
    public List<TListDataType> GenerateList()
    {
        // Get the data from some mysterious place
        RawDataType data = new RawDataType() { ... }
        // Cast it to the required structured data type
        return new List<TListDataType>() { data as TListDataType ??? }
    }
}

然后在运行时加载的另一个程序集中,此原始数据有一些具体的表示形式。ListGenerator本身对这些类型完全不了解。加载包含结构化数据类型的程序集后,将使用反射对其进行检查,以查看可以生成哪些类型的结构化数据。

// Two types of structured application data that can be created from the raw data
public class ListDataTypeA : AbstractListDataType 
{ 
    public static explicit operator ListDataTypeA(RawDataType data) { ... }
}
public class ListDataTypeB : AbstractListDataType 
{ 
    public static explicit operator ListDataTypeB(RawDataType data) { ... }
}

答案是肯定的

data as TListDataType

没有意义。如何实现从 RawDataType 到 ListDataTypeA 的动态强制转换,我知道有一个显式转换可用,但仅在运行时可用?

编辑:

似乎以下工作

(TListDataType)(dynamic)data

我觉得这非常丑陋。考虑到我在这里描述的情况,有没有更好的方法?

将对象显式强制转换为 C# 中仅在运行时可用的泛型类型的另一个对象

如果dynamic方法不适合您 - 请尝试更标准的工厂模式。

由于显式强制转换是在编译时解析的,因此您必须自己手动调用该方法(即通过反射)。

我会走另一条路线,将"Load"方法添加到AbstractListDataType或使用工厂方法/类来创建所需类的项目:

 public abstract class AbstractListDataType { 
     public void Load(RawData data)....
 }
 public class ListGenerator<TListDataType> 
     where TListDataType : AbstractListDataType, new()
     public List<TListDataType> GenerateList()
     {
        RawDataType data = new RawDataType() { ... }
        var item = new T();
        item.Load(data);
        return new List<TListDataType>() { item };
     }
 }

或工厂方法:

 public abstract class ListItemFactory<T> 
 {
      abstract public T CreateFromRawData(RawDataType data);
 }
 public class ListGenerator<TListDataType> 
     where TListDataType : AbstractListDataType
 {
     ListItemFactory<TListDataType> factory;
     public ListGenerator<TListDataType>(ListItemFactory<TListDataType> factory)
     {
         this.factory = factory;
     }
     public List<TListDataType> GenerateList()
     {
        RawDataType data = new RawDataType() { ... }
        return new List<TListDataType>() { factory.CreateFromRawData(data)};
     }
 }