【问题标题】:How to convert class with generic type to class with object as generic type in C#如何在C#中将具有泛型类型的类转换为具有对象作为泛型类型的类
【发布时间】:2016-05-05 15:51:32
【问题描述】:

您好,我使用的是 Visual Studio 2005(因为我需要紧凑的框架支持),而我的问题是泛型。

我创建了一个名为 AbstractDAO 的抽象类,这是我的基础

我正在创建其他类,如 DocumentDAO、HeaderDAO 等,它们代表我数据库中的不同表

我想做的是检索一定数量的上述 DAO 类,但作为一个 AbstractDAO(抽象类有许多我希望使用的具体实现)

我试过的是

AbstractDAO<object> dao = new DocumentDAO();
AbstractDAO<object> dao = (AbstractDAO<object>)new DocumentDAO();
AbstractDAO<T> dao = new DocumentDAO();

我需要上述内容,因为我创建了一个函数,可以将数据从一个表传输到另一个数据库中的另一个类似表,所以它(如果有效)会像这样

AbstractDAO<object> dao_local = new DocumentDAO(local_database);
AbstractDAO<object> dao_remote = new DocumentDAO(remote_database);      
do_transfer(dao_local,dao_remote)

void do_transfer(AbstractDAO<object> from, AbstractDAO<object> to) {
     List<object> items = from.get_all();
     to.insert(items);
}

有没有办法做到以上几点?

【问题讨论】:

  • 伙计——你怎么能将 B 类型的值分配给 A 类型的变量(至少这是你的第一行所做的......)
  • 这就像 c# 基础:AbstractDOA doa = new DocumentDOA();或
  • 这只有在你的类层次结构是这样的时候才有效:
  • 因为 B 是 A 的实现/子类。使用 AbstractDOA doa = new DocumentDOA() 会抛出异常说使用泛型类型 'AbstractDAO' 需要 '1' 类型参数 btw 你所说的确实可以在 Java 中使用,但它似乎在 c# 中不起作用

标签: c# generics


【解决方案1】:

只有当你的类层次结构是这样的时候才有效:

class DocumentDAO : AbstractDAO<object> {
    //...
}

根据您的评论,您似乎有这样的类型层次结构:

class DocumentDAO : AbstractDAO<SomeType> {
    public override SomeType Foo() {
        //...
        return someValue;
    }
    //...
}
class AbstractDAO<T> {
    public abstract T Foo();
    //...
}

您可能想要重构 AbstractDAO 以实现像 IAbstractDAO 这样的非通用接口:

class IAbstractDAO {
    object Foo();
    //...
}

class AbstractDAO<T> {
    public object Foo() {
        return Foo();
    }
    public abstract T Foo();
    //...
}

【讨论】:

  • 我的层次结构就像你上次发布的那样(没有界面)class AbstractDAO&lt;T&gt; { } class DocumentDAO : AbstractDAO&lt;Document&gt; {} 但是添加这个:` public List get_objects() { List items = get_all();以 List 的形式返回项目; } public int insert_object(object obj) { return insert((T)obj); }` in abstract dao 似乎不会抛出错误,所以我想我可以使用它,这不是我想要的(即能够将子类转换为超类)但我可以使用它,谢谢
【解决方案2】:

您可以尝试使用Automapper 像这样传输您的对象:

void do_transfer(AbstractDAO<FirstType> from, AbstractDAO<SecondType> to) 
{
    Mapper.Initialize(cfg=>cfg.CreateMap<FirstType, SecondType>);

    List<FirstType> fromItems = from.get_all();
    List<SecondType> itemsToInsert = 
        Mapper.Map<List<FirstType>, List<SecondType>>(fromItems);
    to.insert(itemsToInsert);
}

默认情况下,自动映射器将映射具有相同名称的字段。您可以为复杂类型映射创建configurations

【讨论】:

  • 我的问题不在于我无法将 from 的类型转换为 to,我的问题是如果可能的话,我希望有一个泛型作为该函数的参数,即do_transfer(AbstractDAO&lt;T&gt; from, AbstractDAO&lt;T&gt; to)do_transfer(AbstractDAO&lt;object&gt; from, AbstractDAO&lt;object&gt; to) 问题是我似乎无法将 AbstractDAO 转换为 AbstractDAO 即使理论上 object 是所有对象的超类
  • 你有没有尝试像DoTransfer&lt;TSource,TDest&gt;(Dao&lt;TSource&gt; source, Dao&lt;TDest&gt; dest)这样声明转移?
【解决方案3】:

AbstractDAO&lt;T&gt; 的任何实现都被编译为一个单独的对象类型,其中 T 被替换为该类型。请参阅“Is generics runtime or compile time polymorphism?”了解更多信息。简而言之,不要让&lt;T&gt; 欺骗你。

这意味着您不能将DocumentDAO 分配给AbstractDAO&lt;object&gt;,就像您可以将String 分配给它一样。此外,泛型类型与继承不同,这似乎是您想要实现的目标。

如前所述,无论哪种情况,都有两种标准解决方案。

第一个是operate on interfaces。您为公共属性创建一个接口,并让AbstractDAO&lt;T&gt; 或任何其他继承自此。然后大部分时间你只是在接口上操作。具体如何组织取决于您。

第二个是执行一个shallow copy的对象。这意味着将值和引用从一个对象复制到另一个对象。为此,您通常使用像AutoMapper 这样的对象映射器。 This tutorial 应该让你开始..

【讨论】:

  • 感谢帮助很大,我选择了另一个解决方案,我将在下面发布,但文献确实帮助我更好地理解了泛型的工作原理
【解决方案4】:

所以我终于找到了我想要做的事情的答案,而不是将 abstractDAO 分配给我创建了一个工厂,该工厂将根据泛型的类型检索所需的 AbstractDAO,并使用此函数

private bool transfer<T>(){
    AbstractDAO<T> local = DAOFactory.get<T>(local_database);
    AbstractDAO<T> remote = DAOFactory.get<T>(remote_database);
    List<T> items = local.get_all();
    foreach (T item in items) {
        remote.insert(item);
    } 
}

这样我可以这样调用这个函数: 转移(); 转();

等等。并进行完全转移

编辑:为了完整起见,这是我创建的工厂

    public static AbstractDAO<T> get<T>(Database database) {
        Type t = typeof(T);
        if (t == typeof(Document)) {
            return new DocumentDAO(database) as AbstractDAO<T>;
        } else if (t == typeof(Header)) {
            return new HeaderDAO(database) as AbstractDAO<T>;
        } etc.
    }

【讨论】:

    猜你喜欢
    • 2020-08-26
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多