Maybe I'm going about this all wrong.
I have a bunch of classes that derive from the "Model" class, a base class with a bunch of common properties and methods. I want them all to implement a set of functionality:
public abstract void Create();
public abstract T Read<T>(Guid ID); //<--Focus on this one
public abstract void Update();
public abstract void Delete();
Then I implement it in a child class like "Appointment" like so:
public override T Read<T>(Guid ID)
{
var appt = db.Appointments.First(a => a.AppointmentID.Equals(ID));
var appointment = new Appointment()
{
DateEnd = appt.dateEnd.GetValueOrDefault(),
Location = appt.location,
Summary = appt.summary
};
return appointment;
}
This throws an exception "Can't implicitly convert type 'Appointment' to T". If I change the method's signature to "public override Appointment Read(Guid ID)", then the compiler says that I've not implemented the abstract method in the child class.
What am I missing? Can anyone give me some code samples?
First, I'd suggest you turn your base class into an interface. If that's an option for you, this will also reduce in slightly less-cluttered code, as you can get rid of the
abstract
andpublic
keywords in the interface declaration and omit theoverride
in the implementing classes.Second, as your implementation of
Appointment.Read
suggests, you could change the method signature ofRead
to return a model object.Both suggested changes would result in the following:
Third, it seems to me that
Read
should really be a factory method. In your current code, you need to first instantiate anAppointment
object before you can call theRead
method to retrieve anotherAppointment
object. This seems wrong to me, from a class design perspective.How about taking
Read
out of the base class/interface and providing it as a static method in all derived/implementing classes? For example:You could also consider moving
Read
into a static (factory) class; however, it would then have to be smart enough to know what kind of object it should return. This would work e.g. if you had a table in your DB that would map a GUID to the corresponding object type.Edit: The last suggestion above used to be this:
Third, if this is correct so far, the next question would be whether or not
Read
should be a static method instead. If so, it could be madestatic
and be moved into a staticModel
class. The method would then act like a factory method that buildsIModel
objects from a DB:There is something funky about this design.
Regardless of whether or not the
Model
class is templated, putting a template parameter on theRead
method doesn't make a lot of sense as an instance method.Usually you'd have something like what Greg D posted.
You need to box and cast. I wonder though why this method is generic?
in your Appointment class add this
If
public abstract T Read<T>(Guid ID);
ofModel
will only ever return derived types ofModel
, consider changing the signature toWould this work?