Thanks David!
Your suggestions helped me quite a bit. I've taken your sample code
and added a driver for it to see how it works and it works great!
Below is the sample working code + driver in case anyone else runs
across a similar issue.
using System;
namespace Sample
{
// Base class for all Model objects.
abstract class Model { }
abstract class Dao { }
// Base class for all Data Access Objects.
abstract class Dao<TModel: Dao where TModel : Model
{
public abstract TModel Get();
}
// Person model.
class Person : Model { }
// Data Access Object for a Person model.
class PersonDao : Dao<Person>
{
public override Person Get()
{
return new Person();
}
}
// Thing model.
class Thing : Model { }
// Data Access Object for a Thing model.
class ThingDao : Dao<Thing>
{
public override Thing Get()
{
return new Thing();
}
}
// Factory that returns the DAO for a model.
class DaoFactory
{
public Dao<TModelGetDao<TModel>() where TModel : Model
{
Dao dao = null;
if (typeof(TModel) == typeof(Person))
{
dao = new PersonDao();
}
else if (typeof(TModel) == typeof(Thing))
{
dao = new ThingDao();
}
return (Dao<TModel>)dao;
}
}
static class Driver
{
static void Main()
{
DaoFactory factory = new DaoFactory();
Dao<PersonpersonDao = factory.GetDao<Person>();
Console.WriteLine("DAO is " + personDao);
Person p = personDao.Get();
Console.WriteLine("Model is " + p);
Dao<ThingthingDao = factory.GetDao<Thing>();
Console.WriteLine("DAO is " + thingDao);
Thing t = thingDao.Get();
Console.WriteLine("Model is " + t);
}
}
}
David Browne wrote:
Quote:
"Tom Spink" <tspink@gmail.comwrote in message
news:OKfovvlvGHA.1424@TK2MSFTNGP02.phx.gbl...
Quote:
Bryan Kyle wrote:
Quote:
Hi All,
>
I'm fairly new to C# and Generics and I'm wondering if anyone has some
suggestions for me.
>
I'm trying to implement a simple DAO framework using generics to keep
my code as clean as I can, however I'm getting an error with what seems
to me to be correct code. The error I'm getting is:
>
Error 1 Cannot implicitly convert type 'Sample.PersonDao' to
'Sample.Dao<Sample.Model>' F:\Documents and Settings\Bryan\My
Documents\Visual Studio
2005\Projects\EventManager\EventManager\Sample.cs 22 24
EventManager
>
Below is a snippet of code that will reproduce compilation error I
receive.
>
namespace Sample
{
// Base class for all Model objects.
abstract class Model { }
>
// Base class for all Data Access Objects.
abstract class Dao<TModelwhere TModel : Model { }
>
// Person model.
class Person : Model { }
>
// Data Access Object for a Person model.
class PersonDao : Dao<Person{ }
>
// Factory that returns the DAO for a model.
class DaoFactory
{
public Dao<ModelGetDao(Model model)
{
if (model is Person)
{
// Compilation error on the next line.
return new PersonDao();
}
>
return null;
>
}
}
}
>
Am I doing something completely wrong here? Is there something I
should be doing? Is there an alternate approach that might work
better?
>
Thanks in advance,
Bryan Kyle
Hi Bryan,
Unfortunately, this version of C# does not support
contravariance/covariance, which is what you're trying to do.
For example, List<Ais not the same, and is not a subset of List<Beven
if
A inherits from B.
>
Actually this will work, it's just hard to convince the compiler that it
will work. In the sample below I made two small changes.
>
First I introduced a non-generic superclass Dao over Dao<TModel>. Without
this Dao<TModelis a family of completely unrelated types, each the root of
its own inheritence hierarchy.
>
Second I declared the method GetDao as a generic method, and introduced an
obfuscating (object) cast to supress the compiler warning and changed the
type comparison from "is" to "==" because "is" includes subclasses, and this
isn't what you want:
>
>
public static Dao<TModelGetDao<TModel>() where TModel : Model
{
if (typeof(TModel) == typeof(Person))
{
// Compilation error on the next line.
return (Dao<TModel>)(object)new PersonDao();
}
>
>
Complete sample:
>
namespace Sample
{
// Base class for all Model objects.
abstract class Model { }
>
>
// Base class for all Data Access Objects.
abstract class Dao { }
>
// Family of base classes.
abstract class Dao<TModel: Dao where TModel : Model
{
>
}
>
// Person model.
class Person : Model { }
>
// Data Access Object for a Person model.
class PersonDao : Dao<Person>
{
>
>
}
>
// Factory that returns the DAO for a model.
class DaoFactory
{
public static Dao<TModelGetDao<TModel>() where TModel : Model
{
if (typeof(TModel) == typeof(Person))
{
// Compilation error on the next line.
return (Dao<TModel>)(object)new PersonDao();
}
>
return null;
>
}
}
}
>
>
David