I have an abstract class "MainClass" which composes "Animal" class. I derive two classes TypeA and TypeB from abstract class which contains common functionality. TypeA and TypeB classes need to be extended to include their own specific functionality.
For example, TypeA would require to add cat functionality under Animal class. So that test application will be accessing the cat class like this typeA._animals._cat?
I know types cannot be added at runtime but is there any other design pattern that could solve my problem?
public abstract class MainClass
{
public Animal _animals;
}
public class Animal
{
public Tiger _tiger;
}
public class Tiger
{
public int type { get { return "Tiger" ; } }
}
public class Cat
{
public int type { get { return "Car" ; } }
}
public class Leopard
{
public int type { get { return "Leopard" ; } }
}
public class TypeA : MainSession
{
//Would like to add type Cat to Animal class
}
public class TypeB : MainSession
{
//Would like to add type Leopard to Animal class
}
Firstly, I believe that Tiger, Cat, Leopard should be inheriting from Animal. Now, you may use a generic base class with type constraints to do the same. For example,
public abstract class MainClass<A> where A:Animal
{
public A _animals;
}
public abstract class Animal
{
...
}
public class Tiger : Animal
{
...
}
public class Cat : Animal
{
...
}
public class Leopard : Animal
{
...
}
public class TypeA : MainSession<Cat>
{
...
}
public class TypeB : MainSession<Leopard>
{
....
}
The first thing you should do is to create an inheritance:
public interface IAnimal
{
string SpeciesName {get; }
}
And implement it:
public class Tiger : IAnimal
{
public string SpeciesName { get { return "Tiger" ; } }
}
public class Cat : IAnimal
{
public string SpeciesName { get { return "Cat" ; } }
}
Let's use it:
public abstract class MainSession
{
private List<IAnimal> _animals;
public IEnumerable<IAnimal> Animals {get { return _animals; }}
proteced void AddAnimal(IAnimal animal)
{
_animals.Add(animal);
}
}
public class TypeA : MainSession
{
public TypeA()
{
AddAnimal(new Tiger());
}
}
public class TypeB : MainSession
{
public TypeB()
{
AddAnimal(new Leopard());
}
}
You could also convert the AddAnimal into a factory method:
public abstract class MainSession
{
private List<IAnimal> _animals;
public IEnumerable<IAnimal> Animals {get { return _animals; }}
protected IAnimal CreateAnimal(string speciesName)
{
// Either use reflection to find the correct species,
// or a simple switch like below:
switch (speciesName)
{
case "tiger":
return new Tiger();
break;
}
}
}
Having the factory in MainSession breaks Single Responsibility Principle, so I would break it out into a separate class.
Yes, Using Abstract Factory Pattern can solve your problem. Check this out on :
http://en.wikipedia.org/wiki/Abstract_factory_pattern
Your main class needs to have a List<Animal> _animals instead of Animal _animals. The Tiger, Cat, and Leopard classes should inherit from the Animal class. You can then put the type property in the Animal base class. At runtime you can add as many Animals to the _animals list as you would like, and since the type property is in the Animal base class you will have access to it in all derived classes.
Related
Why i can't convert implementation of interface which concrete implement generic interface? I need for Cat, Dog etc own interface realisation.
public interface IMarker { }
public class ResultA : IMarker
{
}
public class ResultB : IMarker
{ }
public interface IService<T> where T : IMarker
{
public List<T> DoStuff();
}
public interface ICatService : IService<ResultA>
{ }
public interface IDogService : IService<ResultB>
{ }
public class CatService : ICatService
{
public List<ResultA> DoStuff()
{
return new List<ResultA>();
}
}
public class DogService : IDogService
{
public List<ResultB> DoStuff()
{
return new List<ResultB>();
}
}
public abstract class Animal
{
protected readonly IService<IMarker> _svc;
protected Animal(IService<IMarker> svc)
{
_svc = svc;
}
}
public class Cat : Animal
{
public Cat(ICatService svc) : base(svc)
{
}
}
public class Dog : Animal
{
public Dog(ICatService svc) : base(svc)
{
}
}
CS1503 Argument 2: cannot convert from 'ICatService' to 'IService'
I have DI for services i.e. :
services.AddTransient<ICatService, CatService>();
The reason for such behaviour is that in general case IService<ResultA> is not IService<IMarker> (basically I would argue the same cause for C# classes does not supporting variance which is for a pretty good reason - see more here and here).
In this concrete case everything can be fixed by making the interface covariant and leveraging the covariance of IEnumerable<T>:
public interface IService<out T> where T : IMarker
{
public IEnumerable<T> DoStuff();
}
public class CatService : ICatService
{
public IEnumerable<ResultA> DoStuff() => return new List<ResultA>();
}
public class Cat : Animal
{
public Cat(CatService svc) : base(svc)
{
}
}
But not sure that in your actual code you will be able to.
Or just make the base class generic (if this suits your use case):
public abstract class Animal<T> where T : IMarker
{
protected readonly IService<T> _svc;
protected Animal(IService<T> svc)
{
_svc = svc;
}
}
Original answer
CatService does not implement ICatService, i.e. the fact that ICatService inherits only IService<ResultA> does not mean that they are the same, C# is strongly-typed (mostly :-) language and compiler will consider those two interfaces being different ones (though related). You need either to make CatService to implement ICatService:
public class CatService : ICatService
{
// ...
}
Or register and resolve the IService<ResultA> interface (basically skipping intermediate interface at all):
services.AddTransient<IService<ResultA>, CatService>();
// ...
public Cat(IService<ResultA> svc) : base(svc){}
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
I have a class Dog implementing an interface IAnimal and an IDbSet<Dog> DogSet.
I have the following prototype : MyMethod(IDbSet<IAnimal> AnimalSet)
When trying to do MyMethod(DogSet); I have an error at compilation saying it's not possible to explicitly cast IDbSet<Dog> to IDbSet<IAnimal>
If I try to cast it using MyMethod((IDbSet<IAnimal>)DogSet), I have an error at runtime because it fails to cast.
Why can't I cast it since Dog implement IAnimal ?
Code :
public interface IAnimal{
public String Libelle { get; }
}
public partial class Dog : IAnimal{
public String Libelle {
get {
return "Hello World";
}
}
}
// Can't convert from 'System.Data.Entity.IDbset<Models.Dog>' to 'System.Data.Entity.IDbSet<Interfaces.IAnimal>'
public abstract MyClass : MyAbstractClass{
public MyClass(IModel dbContext) : base(dbContext, dbContext.DOG_IDBSET) { }
}
public abstract class MyAbstractClass{
public MyAbstractClass(Imodel dbContext, IDbSet<IAnimal>){ }
}
Edited code :
// Can't convert from 'System.Data.Entity.IDbset<Models.Dog>' to 'System.Data.Entity.IDbSet<T>'
public abstract MyClass<T> : MyAbstractClass<T> where T : Dog, IAnimal
{
public MyClass(IModel dbContext) : base(dbContext, dbContext.DOG_IDBSET) { }
}
public abstract class MyAbstractClass<T> where T : Dog, IAnimal
{
public MyAbstractClass(Imodel dbContext, IDbSet<T>){ }
}
By setting generic constraints to require a class implementing interface IAnimal you should be able to do this:
public void MyMethod<T>(DbSet<T> animals) where T : class, IAnimal
{
...
}
...and call as:
MyMethod(DogSet);
I'm trying some simple code to understand the generics in C#. The purpose of the code here is to have a trainer that has her own animal and will ask it to do various stuff (for the sake of the example, to jump).
The problem is with the constructor of the trainer. I would like to be able to pass a Dog, or a Cat. They both inherit from the same class, but because I specified the type definition it seems I can't pass them as argument, they can't be both valid. Is there a way to specify a generic class like "Animal" so I could pass a dog or a cat and keep it as a member?
class AnimalDefinition
{
public Fur Fur;
}
class DogDefinition : AnimalDefinition
{
public BarkSound Bark;
}
class CatDefinition : AnimalDefinition
{
public MeowSound Meow;
}
class Animal<TDefinition> where TDefinition : AnimalDefinition
{
public TDefinition Definition;
public void Jump()
{
Console.WriteLine("Jump.");
}
}
class Dog : Animal<DogDefinition>
{
public Dog(DogDefinition def)
{
Definition = def;
}
}
class Cat : Animal<CatDefinition>
{
public Cat(CatDefinition def)
{
Definition = def;
}
}
class Trainer
{
Animal _animal;
public Trainer(Animal myAnimal)
{
_animal = myAnimal;
}
public MakeJump()
{
_animal.Jump();
}
public Listen()
{
// if T is DogDefinition hear barking
// else if T is CatDefinition hear a meowing, etc
}
}
EDIT: Additional question following Chris Berger's answer (which works, but I didn't change the code to keep the question/answer logical). I added a definition member in the Animal class. Is there any way I can access Bark or Meow from inside the Trainer class or will I have to derivate the class Trainer with CatTrainer : Trainer<CatDefinition>? That is, is there something similar to what we have with classes,
if(T is CatDefinition)
{ // Meowing}
else
{}
I think I agree with the first commenter, that you don't necessarily want generics for this, but assuming you have some other reason for wanting generics...
The solution here is to create a class Animal, which Animal<T> derives from.
For example:
public class Animal
{
public virtual void Jump()
{
Console.WriteLine("Jump.");
}
}
public class Animal<T> : Animal where T : AnimalDefinition
{
public override void Jump()
{
//you can override Jump here if you want to
}
}
public class Dog : Animal<DogDefinition> {}
public class Cat : Animal<CatDefinition> {}
Or, actually, a second option is to give Trainer visibility to the generic parameter:
public class Animal<T> where T : AnimalDefinition
{
public void Jump()
{
Console.WriteLine("Jump.");
}
}
public class Dog : Animal<DogDefinition> {}
public class Cat : Animal<CatDefinition> {}
public class Trainer<T> where T : AnimalDefinition
{
Animal<T> _animal;
public Trainer(Animal<T> myAnimal)
{
_animal = myAnimal;
}
public MakeJump()
{
_animal.Jump();
}
}
And as a tangent... this might be a good place to use a self-referential generic.
public class Animal<T> where T : Animal<T> { }
public class Dog : Animal<Dog> { }
Here's a little more reading on that pattern: https://blogs.msdn.microsoft.com/simonince/2008/06/12/generics-the-self-referencing-generics-pattern/
I'm just learning about C# extension methods, and was wondering if I can use it to provide a default implementation for an interface.
Say:
public interface Animal {
string MakeSound();
}
public static string MakeSound(this Animal) {
return "";
}
Then
public class Dog : Animal {
string MakeSound() {
return "Bark";
}
}
public class Porcupine : Animal {
}
And last:
Animal dog = new Dog();
Animal porcupine = new Porcupine();
Print(dog.MakeSound());
Print(porcupine.MakeSound());
I'd like the porcupine and any other animals that have not explicitly implemented MakeSound to use the default extension method that returns an empty string, but dog and any animal that does have an explicit implementation return its own implementation such as "Bark".
So my questions:
1. Is this doable?
2. If not, is there any other way to implement default behavior for an interface?
Abstract class instead of interface is not an option because C# doesn't support multiple inheritance and my classes are inheriting behavior of another class.
I'd generally recommend a base class, however, if that's out, you can do something like this:
public interface IAnimal { }
public interface INoisyAnimal : IAnimal {
string MakeSound();
}
public static class AnimalExtensions {
public static string MakeSound(this IAnimal someAnimal) {
if (someAnimal is INoisyAnimal) {
return (someAnimal as INoisyAnimal).MakeSound();
}
else {
return "Unknown Noise";
}
}
}
public class Dog : INoisyAnimal {
public string MakeSound() {
return "Bark";
}
}
public class Porcupine : IAnimal { }
This makes every IAnimal look like a INoisyAnimal even if it isn't really one. For example:
IAnimal dog = new Dog();
IAnimal porcupine = new Porcupine();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
However, this still isn't an actual implementation of the interface. Notice that despite appearances
Console.WriteLine(porcupine is INoisyAnimal); // false
Another option might be to create a wrapper to extend your base class when new functionality is needed:
public class NoisyAnimalWrapper : INoisyAnimal {
private readonly IAnimal animal;
public NoisyAnimalWrapper(IAnimal animal) {
this.animal = animal;
}
public string MakeSound() {
return "Unknown Noise";
}
}
public static class AnimalExtensions {
public static INoisyAnimal Noisy(this IAnimal someAnimal) {
return someAnimal as INoisyAnimal ??
new NoisyAnimalWrapper(someAnimal);
}
}
Then you can create a INoisyAnimal from any IAnimal whenever you need to:
INoisyAnimal dog = new Dog();
INoisyAnimal porcupine = new Porcupine().Noisy();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
You could also make the wrapper generic (e.g. NoisyAnimal<T> where T : IAnimal, new) and get rid of the extension method altogether. Depending on your actual use case, this may be preferable to the previous option.
I don't know exactly what is your real case or if you are just experimenting but, if only some animals are noisy, then it might a good case for Interface segregation.
For example:
public class Dog : IAnimal, INoisy
{
public string MakeSound()
{
return "Bark";
}
}
public class Porcupine : IAnimal
{
}
Then, you will only call MakeSound or objects that are actually noisy.
How about something like this? It allows you to avoid having a base class, and you can do what you had in mind, right?
public interface Animal
{
// Fields
string voice { get; }
}
public static class AnimalHelper
{
// Called for any Animal
public static string MakeSound(this Animal animal)
{
// Common code for all of them, value based on their voice
return animal.voice;
}
}
public class Dog : Animal
{
public string voice { get { return "Woof!"; } }
}
public class Purcupine : Animal
{
public string voice { get { return ""; } }
}