如何在 C# 中将具有泛型类型的类转换为具有对象作为泛型类型的类

本文关键字:泛型类型 对象 转换 | 更新日期: 2023-09-27 18:32:11

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

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

从那里我正在创建其他类,如DocumentDAO,HeaderDAO等,它们代表我的数据库上的不同表

我希望

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

我尝试的是

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);
}

有没有办法做到以上?

如何在 C# 中将具有泛型类型的类转换为具有对象作为泛型类型的类

这只有在您的类层次结构如下所示时才有效:

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();
    //...
}

AbstractDAO<T>的任何实现都会编译为单独的对象类型,其中 T 被替换为类型。请参阅"泛型运行时还是编译时多态性?",了解有关如何发生这种情况的更多信息。简而言之,不要让<T>欺骗你。

这意味着您不能将DocumentDAO分配给AbstractDAO<object>,就像不能将 String 分配给它一样。泛型类型也与继承不同,这似乎是您要实现的目标。

如前所述,在任何一种情况下,都有两种标准解决方案。

首先是在接口上操作。您可以为公共属性创建一个接口,并从中继承AbstractDAO<T>或任何其他接口。然后大多数时候你只是在接口上操作。具体如何组织它取决于您。

第二种是执行对象的浅拷贝。这意味着将值和引用从一个对象复制到另一个对象。为此,您通常使用像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);
}

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

所以我终于找到了我想要做的答案,而不是将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.
    }