Monday, May 21, 2012

Typing generic interfaces

I'm trying to create two interface hierarchies, one for the business model objects and one for the ui. I know it's important to have loose coupling between the layers but part of the application will require drawing diagrams so I need the model objects to be readily available to their corresponding graphical representations and I have a common layer holding interfaces for the model objects..



Common class library code:

Public interface IBase {}
Public interface IBookObject : IBase {}
Public interface ITapeObject : IBase {}

Public class Book : IBookObject {}

Graphics layer code:

Public interface IModelObject<T>

{

T ModelObject { get; set; } // might be a book or tape , etc

}


Public class GraphicObject<T> : IModelObject<T>

{

Public T ModelObject { get; set; }

}


Code use:

IBookObject bk = new Book();

Var go = new GraphicObject<IBookObject>(); // will fail later

//var go = new GraphicObject<IBase>(); // will succeed later

go.ModelObject = bk;

If( go is IModelObject<IBase>) // can't use is IModelObject<IBookObject> as go might be GraphicObject<ITapeObject>

{
Debug.WriteLine("Success");
}


So if I want to test for IBase (and then access ModelObject), I have to make sure that the original object was created with IBase and not a derived interface, and this seems like a cause of bugs later. my questions are:



1) Am I doing something horrible?! :) I might be overlooking a better approach..



2) failing that, is there some way of using the new contravariance c# 4 techniques to make the is line test for any interface deriving from IBase? Alternatively I think it would work if IBook didn't inherit from IBase, but Book (and Tape) implemented both IBook and IBase separately.



3) failing that, is there any way to prevent construction of GraphicObject<IBookObject>() and GraphicObject<ITapeObject>()?



Thank you!





No comments:

Post a Comment