How to Access Methods/Interface on Nested Generic Classes - c#

I have need for nesting Generics, as in A< B< Base > > .
When I do this, only the outer properties (A) are exposed. I can not figure out how to access (B)'s methods, etc. I then tried to access the interfaces internally with the same results.
(edit) To clarify the use case, the solution I need should work with
public class C : A < B < Base > > or
public class C : B < A < Base > >
I don't need those to result in identical classes, but both definitions have the corresponding methods. As you might suspect, I am trying to use this to implement common functionality in a modular mode across several objects. Extension methods get me close, but they won't allow overridden behavior as this solution would (if it is achievable).
I have attached test code, which shows the problems perhaps more clearly than I ca.
using System;
using System.Reflection;
namespace ArchitecturalTestGround
{
public interface IBase
{
void BaseMethod1();
}
public interface IA : IBase
{
void AMethod();
}
public interface IB : IBase
{
void BMethod();
}
public class Base : IBase
{
public void BaseMethod1() { }
}
public class A<T> : IA where T : IBase
{
public void BaseMethod1() { }
public void AMethod() { }
}
public class B<T> : IB where T : IBase
{
public void BaseMethod1() { }
public void BMethod() { }
}
public class Test1 : A<B<Base>>
{
}
public class Test2 : B<A<Base>>
{
}
public class Program
{
public static void Main(string[] args)
{
Test1 e1 = new Test1();
Test2 e2 = new Test2();
Console.WriteLine("Test1 - A<B<Base>>");
foreach (MemberInfo mi in typeof(Test1).GetMembers())
{
Console.WriteLine($" {mi.Name}.{mi.MemberType}");
}
if (e1 is IB) { Console.WriteLine(" Supports IB"); }
if (e1 is IA) { Console.WriteLine(" Supports IA"); }
Console.WriteLine();
Console.WriteLine("Test2 - B<A<Base>>");
foreach (MemberInfo mi in typeof(Test2).GetMembers())
{
Console.WriteLine($" {mi.Name}.{mi.MemberType}");
}
if (e2 is IB) { Console.WriteLine(" Supports IB"); }
if (e2 is IA) { Console.WriteLine(" Supports IA"); }
Console.ReadKey();
}
}
}

Test1 is inheriting from A<T> (regardless of what T is) and A<T> inherits from from IA, which in turn inherits from IBase, so you will only see the methods from that inheritance chain:
From A<T>:
public void BaseMethod1() { }
public void AMethod() { }
From IA:
void AMethod();
From IBase:
void BaseMethod1();
(By the way, notice from your code sample that you would probably get a compiler warning because of BaseMethod1).
I think I see where you are going with this. You have probably encountered a situation where you need to inherit from two classes. Multiple class inheritance is not possible in C#. There are some ways around it though.
Generally speaking, if you encounter a situation like this, more times than not it means you need to rethink your design. If you are still interested on the subject, check this guy out:
Multiple Inheritance in C#

Is it possible to change your definitions like this?
public class A<T> : IA where T : IBase
{
T NestedGeneric;
public A(T nested)
{
NestedGeneric = nested;
}
public void BaseMethod1() { }
public void AMethod() { }
}
public class Test1 : A<B<Base>>
{
public B<Base> NestedGeneric;
public Test1(B<Base> nested) : base(nested)
{
NestedGeneric = nested;
}
}
This allows you do do e1.NestedGeneric.BMethod();.

Related

C# generic inheritance, base class casting

I wanted to make the following inheritance with included generics, but the final cast
a as A<XBase> always results in null, because the cast is not valid. Could anybody elaborate on why this cast would be invalid, as well as maybe a solution to this problem.
public class XBase {}
public interface A<T> where T : XBase
{
//Edited
void Method(T param);
}
public class Implementor : A<Implementor.ImplementorX >
{
public class ImplementorX : XBase {public int a;}
//Edited
void Method(ImplementorX param) {}
}
public class HelloWorld
{
public static void Main(string[] args)
{
var a = new Implementor();
var castRes = a as A<XBase>;
Console.WriteLine(castRes != null);
}
}
see live example https://rextester.com/BTNVT61833
EDITED: Added a method to interface A<T> bc else it could be solved with #DavidG's response
If you make an explicit cast:
var castRes = A<XBase>(a);
then you will see the following error:
Unable to cast object of type '' to type '`
Why? In my view, it is better to understand using real world example. I've renamed classes based on this explanation. There are comments which maps explanations to your classes in question.
Abstractions:
// XBase
public class Animal { }
// class ImplementorX : XBase {public int a;}
public class Bird : Animal
{
public string WingColor { get; set; }
}
// interface A<T> where T : XBase
public interface IHat<T> where T : Animal
{
void Hide(T param);
T Pull();
}
Concrete implementations:
// class Implementor : A<Implementor.ImplementorX >
public class Peacock : IHat<Bird>
{
// void Method(ImplementorX param) {}
void IHat<Bird>.Hide(Bird param)
{ }
public Bird Pull()
{ }
}
and how it can be called:
public static void Main(string[] args)
{
Peacock peacockHat = new Peacock();
IHat<Animal> animalHat = (IHat<Animal>) peacockHat; // runtime error 'Unable to cast
// object of type 'HelloWorld.Peacock' to type 'HelloWorld.IHat`1
// because
animalHat.Hide(new Dolphin()); // Hide a dolphin in a peacock hat?
}
So we cannot hide hat of Peacock from Dolphin. It is not okay. CLR prevents us from making inappropriate actions.
In short:
In short, imagine you have two animals such as Wolf and Sheep. And these classes implements IAnimal interface:
public interface IAnimal
{ }
public class Wolf: IAnimal
{ }
public class Sheep : IAnimal
{ }
So Sheep, Wolf classes implement the inherited interface IAnimal:
IAnimal
/ \
/ \
Sheep Wolf
And then these animals can be put in cage:
public class Cage<T> where T : IAnimal
{
public void Put(T animal)
{ }
}
Then you create a cage for Sheep. After that somebody wants to cast Sheep cage to IAnimal:
Cage<Sheep> sheepCage = new Cage<Sheep>();
sheepCage.Put(new Sheep());
Cage<IAnimal> animalCage = (Cage<Wolf>)sheepCage; // compile error
// if there were no error, then you will be able to do:
animalCage.Put(new Wolf()); // it is not good idea

Generic interface and covariance - fighting the InvalidCastException

This is probably a classic covariance/contravariance question, it looks like it should work but I'm probably missing a trick.
I'm attempting to return a less derived type from a factory method, but I find that I cannot cast the more specialized concrete instance to a less derived base type.
public class AnimalSettings { ... }
public class CatSettings : AnimalSettings { ... }
public interface IAnimalService<TSettings> { ... }
public abstract AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings { ... }
public class CatService : AnimalService<CatSettings> { ... }
Then, in a factory method I have:
public static IAnimalService<AnimalSettings> GetAnimalService(AnimalType selector)
{
switch (selector)
{
case AnimalType.Cat:
return (IAnimalService<AnimalSettings>) new CatService();
break;
}
}
and the intention is to be able to do the following:
var service = MyServiceFactory.GetAnimalService(AnimalType.Cat);
service.DoAnimalBehavior();
This compiles fine, but at runtime my code is failing in the attempted cast return (IAnimalService<AnimalSettings>) new CatService();, with an InvalidCastException.
How should I be casting my more derived type to a less derived type so that callers can use that interfaced base type to invoke functionality?
Changing the cast to (IAnimalservice<CatSettings>) new CatService() does work, but it's intended that the caller receives a IAnimalservice<AnimalSettings> so that it can handle any sort of animal (In other words, the caller should not be using any of the more specialized types). Should I be specifying an in or out as part of the generic definition somewhere?
By giving a complete example it would be much easier to help. ;-)
So here is the working code. And as Sweeper already mentioned, you need to add the out parameter at the interface to make it work.
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}

How can I have a class pass its own type in the generics of a parameter name?

I have got two abstract classes: Particle and ParticleHub<T> where T : Particle.
I want, when I inherit Particle, for its constructor to require a ParticleHub of its respective type to be passed as a parameter. I want its constructor to be like this:
ParticleHub</*type of the inheriting class*/> _particleHub;
public Particle(ParticleHub</*type of the inheriting class*/> particleHub, OtherParameters otherParameters)
{
_particleHub = particleHub;
//use other parameters
}
If I write ParticleHub<typeof(this)> I get overloaded with errors that make me think I broke the syntax for the rest of the file. If I do ParticleHub<this.GetType()> I get the same problem, but only with fewer errors. Though with that one, I can understand that I can't use a function in a parameter type like that.
So how do I go about this?
Simple example below of an interface and generic pattern
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
IChair chair = new Chesterfield<Arm>(new Arm());
chair.Sit();
Console.Write(chair.HasSat());
}
}
public interface IChair
{
void Sit();
bool HasSat();
}
public interface IPart
{
}
public class Chesterfield<TPart> : Chair<TPart> where TPart : IPart
{
public Chesterfield(TPart part) => _part = part;
private bool _hasSat;
private readonly TPart _part;
public override void Sit()
{
_hasSat = true;
}
public override bool HasSat() => _hasSat;
}
public abstract class Chair<TPart> : IChair where TPart : IPart
{
public abstract void Sit();
public abstract bool HasSat();
}
public class Arm : IPart
{
}
public class Back : IPart
{
}
public class Leg
{
}
You have no other choise i think but to pass the type as other generic. See the exaple how it is done in terms of fluent builders as I think it is very close what You want to have: Link.
Like:
FePatricle<T, U> where T: Particle, U: FeParticle<T, U>
Looks crazy but it should do the trick in the constructor:
public FeParticle(ParticleHub<U>...
EDIT:
Or more likely as far as I understand:
FePatricle<T>: Particle where T: FeParticle<T>
So FePartivle extends Particle and it carries with itself its own type T?
Passing the inherited class itself, as below.
public abstract class Particle
{
}
public abstract class ParticleHub<T> where T : Particle
{
}
public class k1 : Particle
{
ParticleHub<k1> _particleHub = null;
public k1(ParticleHub<k1> ph)
{
_particleHub = ph;
}
}

Extending multiple/different objects based on required functionality?

Is there a design pattern that allows me to define an object as extending another object depending on the functionality that I need? For example if I have the following classes:
using System;
namespace C_
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("------------------------------------------------");
C c = new C();
Console.WriteLine("------------------------------------------------");
D d = new D();
Console.WriteLine("------------------------------------------------");
}
}
public abstract class A
{
public A() {}
public void DoSomething()
{
Console.WriteLine("Doing something");
}
public virtual void CallSomething()
{
DoSomething();
}
}
public abstract class B : A
{
public B() {}
public override void CallSomething()
{
Console.WriteLine("Do something extra");
DoSomething();
}
}
public class C : A
{
public C()
{
CallSomething();
}
}
public class D : B
{
public D()
{
CallSomething();
}
}
}
Essentially class B is an extension of class A. The minimum functionality I want is defined in class A while in some cases I may need more which is defined in class B. Is it possible to have another class extend either A or B depending on what functionality is required at runtime? I could create separate classes each extending A or B but that would lead to a lot of repeated code
EDIT: Added a more concrete example. Classes C and D have the same functionality except that D requires a little more done before it can proceed hence extending B instead of A. Is there a design pattern where I wouldn't need class D and can pick and choose the functionality of C based on what I need?

Generics, Covariance/Contravariance, etc

So I have some Java code that makes extensive use of generics that compiles just fine. I ported it over to C# as follows:
interface IFoo1 { }
interface IFoo2 { }
interface IBar<T, K>
where T : IFoo1
where K : IFoo2 {
List<T> GetFoo1s();
void AddAFoo1(T foo1);
List<K> GetFoo2s();
void AddAFoo2(K foo2);
}
interface IBlip<T>
where T : IBar<IFoo1, IFoo2> {
T DoBlip(string input);
void DoBlip2(T input);
}
interface IConverter<T, K>
where T : IBar<IFoo1, IFoo2>
where K : IBar<IFoo1, IFoo2> {
K Convert(T input);
}
class FooA1 : IFoo1 { }
class FooB1 : IFoo1 { }
class FooA2 : IFoo2 { }
class FooB2 : IFoo2 { }
class BarA : IBar<FooA1, FooA2> {
public List<FooA1> GetFoo1s() { return null; }
public void AddAFoo1(FooA1 foo1) { }
public List<FooA2> GetFoo2s() { return null; }
public void AddAFoo2(FooA2 foo2) { }
}
class BarB : IBar<FooB1, FooB2> {
public List<FooB1> GetFoo1s() { return null; }
public void AddAFoo1(FooB1 foo1) { }
public List<FooB2> GetFoo2s() { return null; }
public void AddAFoo2(FooB2 foo2) { }
}
class BlipA : IBlip<BarA> {
public BarA DoBlip(string input) { return null; }
public void DoBlip2(BarA input) { }
}
class BlipB : IBlip<BarB> {
public BarB DoBlip(string input) { return null; }
public void DoBlip2(BarB input) { }
}
class ConverterImplementation : IConverter<BarA, BarB> {
public BarB Convert(BarA input) {
return null;
}
}
When I compile this, it complains that, for example, with the ConverterImplementation, that BarA cannot be implicitly converted to IBar. I guess there's something that I'm fundamentally missing here. Could someone shed some light on it? Thanks.
Generic type parameters are by default neither contravariant nor covariant, but can be made one or the other via the "in" and "out" keywords.
In the case of IBar<T, K>, both type parameters are used as both inputs and outputs, so you cannot make them either contravariant or covariant. If you refactored it into two interfaces, one in which T is used only for input and K only for output, and one in which T is used only for output and K only for input, then you could make each type parameter covariant or contravariant based on its usage.
IBar is not a read only interface, therefore you may not achieve convariance in C#. You need to refactor and extract a read only interface, e.g. ReadOnlyBar, and do convariance on that interface. (disclaimer - not an expert on C#)
On the other hand, Java's wildcard can turn an interface to read-only and convariant interface, so IBar<? extends Animal> is read-only convariant, and IBar<? extends Tiger> is a subtype of it. That's cool and all, until your code is littered with lots of wildcards.

Categories