1

Hello I'm using Visual Studio 2005 (because I need compact framework support) and my problem is with generics.

I have created an abstract class called AbstractDAO which is my base

From that I am creating other classes like DocumentDAO,HeaderDAO etc which represent different tables on my database

What I wish to do is retrieve a certain number of the above mentioned DAO classes, but as an AbstractDAO (the abstract class has a number of concrete implementations that I wish to use)

What I tried is

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

I need the above because I have created a function that transfers data from one table to another similar table in a different database, so it would (if it worked) go something like this

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

Is there any way to do the above?

7
  • Dude - how do You excepct to be able to assign a value of type B to a variable of type A (at least that's what Your first line does..) Commented Jan 28, 2016 at 10:26
  • This is like c# basics : AbstractDOA doa = new DocumentDOA(); or Commented Jan 28, 2016 at 10:27
  • This will only work if you class hierachy is like: Commented Jan 28, 2016 at 10:30
  • because B is an implementation/subclass of A. using AbstractDOA doa = new DocumentDOA() throws an exception saying Using the generic type 'AbstractDAO<T>' requires '1' type arguments btw what you said does indeed work in Java , but it seems that it does not work in c# Commented Jan 28, 2016 at 10:35
  • 1
    stackoverflow.com/questions/8766794/… Commented Jan 28, 2016 at 10:37

4 Answers 4

1

That will only work if your class hierachy is like this:

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

By your comment it seems like you have a type hierarchy like this:

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

You probably want to refactor AbstractDAO to implement a non generic interface like IAbstractDAO:

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

class AbstractDAO<T> {
    public object Foo() {
        return Foo();
    }
    public abstract T Foo();
    //...
}
Sign up to request clarification or add additional context in comments.

1 Comment

My hierarchy is like the one you posted last (without the interface) class AbstractDAO<T> { } class DocumentDAO : AbstractDAO<Document> {} But adding this: ` public List<object> get_objects() { List<T> items = get_all(); return items as List<object>; } public int insert_object(object obj) { return insert((T)obj); }` in abstract dao seems to not throw errors so I guess I can use that, it's not exactly what I wanted (i.e. being able to cast the subclass to the superclass) but I can work with that , thanks
1

Any implementation of AbstractDAO<T> is compiled to a separate object type where T is replaced with the type. See "Is generics runtime or compile time polymorphism?" for more information on how this happens. In short, don't let the <T> fool you.

This means that you can't assign DocumentDAO to AbstractDAO<object> any more than you can assign String to it. Also a generic type is not the same as inheriting, which seems to be what you are trying to achieve.

In either case there are two standard solutions, as already mentioned.

The first is to operate on interfaces. You create an interface for the common properties and have AbstractDAO<T> or any other inherit from this. Then most of the time you simply operate on interfaces. Exactly how you organize it is up to you.

The second is to perform a shallow copy of the object. This means copying values and references from one object to the other. For this you usually use an object mapper like AutoMapper. This tutorial should get you started..

1 Comment

Thanks that helped a lot, I went with another solution, I will post it below, but the literature certainly helped me understand the workings of generics better
0

You can try to use Automapper to transfer your objects like this:

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

By default automapper will map fields with same names. You can create configurations for complex type mapping.

2 Comments

my problem isn't that I can't convert the type of from to to, my problem is that i want to have a generic as an argument to that function if possible I.e. either do_transfer(AbstractDAO<T> from, AbstractDAO<T> to) or do_transfer(AbstractDAO<object> from, AbstractDAO<object> to) the thing is that I can't seem to cast AbstractDAO<T> to AbstractDAO<object> even though in theory object is the superclass of all objects
Did you try to declare transfer like this DoTransfer<TSource,TDest>(Dao<TSource> source, Dao<TDest> dest) ?
0

So I finally found the answer to what I was trying to do, instead of assigning abstractDAO to something I created a factory that would retrieve the required AbstractDAO according to what type the generic was, and used this function

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

That way I can call this function like this: transfer< Document >(); transfer< Header >();

etc. and do a full transfer

edit: just for completeness' shake this is the factory I created

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.