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

时间:2016-01-28 10:19:21

标签: c# generics

您好我使用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);
}

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

4 个答案:

答案 0 :(得分: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();
    //...
}

答案 1 :(得分:1)

AbstractDAO<T>的任何实现都被编译为单独的对象类型,其中T被替换为类型。见&#34; Is generics runtime or compile time polymorphism?&#34;有关如何发生这种情况的更多信息。简而言之,不要让<T>欺骗你。

这意味着您无法将DocumentDAO分配给AbstractDAO<object>,只能为其分配字符串。通用类型也与继承不同,这似乎是您要实现的目标。

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

第一个是operate on interfaces。您可以为公共属性创建一个接口,并使用AbstractDAO<T>或其他任何继承。然后大多数时候你只是简单地操作接口。具体如何组织它取决于你。

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

答案 2 :(得分:0)

您可以尝试使用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);
}

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

答案 3 :(得分:0)

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

这样我可以像这样调用这个函数:     转移&LT;文件&gt;();     转移&LT;标题&gt;();

等。并进行全面转移

编辑:只是为了完整性&#39;摇这是我创建的工厂

    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.
    }