So here is the code:
interface A<T>
{
T Save();
}
interface B : A<B>
{
}
class BusinessBase<T>
{
T Save();
}
class D<T, U> : BusinessBase<T>
where T : BusinessBase<T>
where U : B<U>
{
new U Save()
{
base.Save(); // this is where the error is because T can't be converted to U
}
}
class Concrete : D<Concrete , B>, B
{
}
So with all that what I am hoping to have is a base class that defines all the methods of A which are really just redirects to methods in C. But to support IoC and CSLA it has to be this way. So what I am looking for is to have the save in D return U not T so as to match the interface signature..
I have been staring at this for a while and can't seem to figure out what I am missing.
Ok so I just want to apologize for some of the bad code that was in my example. But hopefully if you looked at it for a while you could see where it went wrong. But here is the answer that I have come up with. I think there might be a better way in the conversion but I wanted a solution that didn't require me changing the BusinessBase class as that is a core CSLA component and not one I want to change. Here is the code I have come up with that is working:
interface A<T>
{
T Save();
}
interface IConcreteInterface : A<IConcreteInterface>
{
}
class BusinessBase<T>
where T : BusinessBase<T>
{
public T Save()
{
return (T)this;
}
}
class D<T, U> : BusinessBase<T>
where T : BusinessBase<T>, A<U>
where U : A<U>
{
public new U Save()
{
return (U)(object)base.Save();
}
}
class ConcreteClass : D<ConcreteClass, IConcreteInterface>, IConcreteInterface
{
}
The change that made it work was this: return (U)(object)base.Save();
Before I was didn't put in the (U) cast in the sample because it woudn't compile like that. As there is no relationship between T and U that can be determined. So the only way around this is to cast the return T from Save to (object) which of course will then be capable of casting to anything.
You notice I also added a type constraint for a little added protection against cast errors in that I am making sure that T is of type A and that U is of type A. That ensures that both types have the same interface.
If someone has something prettier I am open to suggestions. But for now this is working and I feel somewhat good about it. You can do what I did which was at least require T to implement It isn't pretty and you can enforce a little more