views:

78

answers:

2

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.

+1  A: 

I think you'll need:

class BusinessBase<T> : B
{
    T Save();
}

and:

class D<T, U> : BusinessBase<T>
    where T : BusinessBase<T>
    where U : B<U>
{
    new U Save()
    {
        return base.Save();
    }
}

I think the error is because you don't have any implicit or explicit connection between BusinessBase<T>.Save() and the B<U> that you're trying to return. Is this possible or will it break other interfaces?

Have you looked through Expert C# 2008 Business Objects, which covers the CSLA framework?

Jim Schubert
no I don't have that book. I will have to see if I can get a copy of it. But you're right there isn't a defined connection between the two. Though there is a connection between the T of BusinessBase<T> and U of B<U>. As U is an interface which T implements. Was hoping through that relationship there was something there that I was overlooking.
spinon
+1  A: 

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

spinon