In order to save code, I tried setting up something like this:
namespace Base {
class Application<CCOMPONENT1, CCOMPONENT2>
where CCOMPONENT1 : Component1
where CCOMPONENT2 : Component2 {
public CCOMPONENT1 component1;
public CCOMPONENT2 component2;
}
class Component<CAPPLICATION>
where CAPPLICATION : Application {
public CAPPLICATION application;
}
class Component1<CAPPLICATION> : Component<CAPPLICATION>;
class Component2<CAPPLICATION> : Component<CAPPLCIATION>;
...
}
namespace Derived {
class Application : Base.Application<Component1, Component2>;
class Component1 : Base.Component1<Application>;
class Component2 : Base.Component2<Application>;
...
}
Obviously, it's not working. When I specify the generic component types for the Application
class, I have to specify the Application
class as generic type, which in turn requires me to again specify the generic component types, and so on. Very much like a circular reference.
What I'd like to achieve is this: The Base.Application
class shall contain references to Base
components only, and
the Base.Component
classes shall contain a reference to the Base
application only.
However, the Derived.Application
class shall contain references to Derived
components,
and the Derived.Component
classes shall contain a reference to the Derived
application.
Although I have played around with generics for quite a while, I still can't wrap my head around this problem. Is this even possible at all? Are there any workarounds or maybe even cleaner approaches to what I'm trying to do?
CodePudding user response:
With the pointers I got from the comments, I figured it out:
namespace Base {
public class Application<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TAPPLICATION : Application<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT1 : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT2 : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> {
public TCOMPONENT1 Component1;
public TCOMPONENT2 Component2;
}
public class Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TAPPLICATION : Application<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT1 : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT2 : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> {
public TAPPLICATION Application;
}
public class Component1<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TAPPLICATION : Application<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT1 : Component1<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT2 : Component2<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> {
}
public class Component2<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> : Component<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TAPPLICATION : Application<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT1 : Component1<TAPPLICATION, TCOMPONENT1, TCOMPONENT2>
where TCOMPONENT2 : Component2<TAPPLICATION, TCOMPONENT1, TCOMPONENT2> {
}
}
namespace Derived {
public class Application : Base.Application<Application, Component1, Component2> {
}
public class Component1 : Base.Component1<Application, Component1, Component2> {
}
public class Component2 : Base.Component2<Application, Component1, Component2> {
}
}
The key was to supply all generic types to all classes in the Base namespace. Looks a bit convoluted, but I can easily exchange components as I see fit in the Derived namespace, and in the I end I got exactly what I wanted.
Thanks!