Reputation: 3119
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?
Upvotes: 1
Views: 1568
Reputation: 3119
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.
}
Upvotes: 0
Reputation: 12314
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..
Upvotes: 1
Reputation: 172
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.
Upvotes: 0
Reputation: 2617
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();
//...
}
Upvotes: 1