Creating generic types with enum values - c#

I'd like to be able to create new generic types using enum values. I believe this is possible with C++ templates, but I don't know if it's possible to do with C#.
So what I'd like to do is:
public class MyClass <T>
{
public void Do<T>() {}
}
public enum Metals
{
Silver, Gold
}
and I'd like to pass in an enum like:
var myGoldClass = new MyClass<Metals.Gold>();
I guess I could create classes called Gold, Silver to achieve this, but I quite like having an enum to constrain the types of my generic class.
The reason I want something like this in the real world is I'm creating an event aggregator (a publish-subscribe model) and I'd want my subscribers to subscribe to messages of a certain type T. So i thought it would be nice if i could have my subscribers subscribe using enums.
EDIT:
To clarify, Metals.Gold is just an example enum. I'd like the client library to create their own enums\classes and use it instead. I'm not defining the enum myself.

Using enum values as generic parameters is not possible. In cases like that you should probably use inheritance:
public abstract class Metal
{
protected Metals MetalType { get; private set; }
protected Metal(Metals metal)
{
MetalType = metal;
}
}
public class Gold : Metal
{
public Gold() : base(Metals.Gold)
{
}
}
Going further, the part of the question about PubSub implementation is too broad as a lot of things should be taken in consideration. Here is an example where you may some useful ideas:
public class EventHub
{
// only one receiver per message type is allowed to simplify an example
private static readonly ConcurrentDictionary<MessageTypes, IReceiver> receivers =
new ConcurrentDictionary<MessageTypes, IReceiver>();
public bool TrySubscribe(MessageTypes messageType, IReceiver receiver)
{
return receivers.TryAdd(messageType, receiver);
}
public void Publish(IMessage message)
{
IReceiver receiver;
if (receivers.TryGetValue(message.MessageType, out receiver))
{
receiver.Receive(message);
}
}
}
public interface IMessage
{
MessageTypes MessageType { get; }
string Text { get; set; }
}
public interface IReceiver
{
void Receive(IMessage message);
}

This is not possible as T as to be a Type and not a value.
Maybe I don't understand your problem but why don't you do something like that :
public class MyClass
{
private readonly Metals _metal;
public MyClass(Metals metal)
{
_metal = metal;
}
public void Do()
{
//using _metal here
}
}
var myGoldClass = new MyClass(Metals.Gold);

Related

How to call a method of a class embedding List<X> and List<Y>, and of Y, from the X elements themselves?

I though I would easily find an answer to this question but I couldn't find yet.
Let's say I have the following classes :
public class Universe
{
public list<Human> Humans { get; set; }
public list<Animal> Animals { get; set; }
public God AlphaOmega { get; set; }
public void UniverseAction()
{
//dosmthg
}
public Animal FindAnAnimal()
{
//find an animal
}
}
public class Animal
{
//many Animal things
public void AnimalyStuff()
{
//DoSmthg
}
}
public class God
{
public bool CantTouchThis = true;
}
public class Human
{
//many Human things
public void CallingUniverseAction()
{
//How to?
}
public void CallingAnimalyStuff()
{
}
}
Note that those names are purely given as examples, I could have used A, B, C & D.
So I want that all humans be able to call UniverseAction() so from a specific Human I can use it.
I also want that humans be able to call AnimalyStuff() so a specific Human would need to access the FindAnAnimal in Universe to retrieve a specific Animal and do the AnimalyStuff()
For a while when dealing with this kind of requirement I used to pass Universe in the constructor of Human. Though I don't want that Human can expose all method / parameters of Universe. For instance, Human should not interract with AlphaOmega
What would be the most appropriate way to do it?
Is it through an action delegate that I'll pass in the constructor? If so how, I never used action delegates. Also will I not end up with passing many delegates if I want Human to access many methods?
You have a couple options available to you if you want to limit the available information to Human.
If you are okay with only hiding the information, where it is still there, but not accessible unless you explicitly un-hide it consider using a Interface to limit the available members.
If you are okay with the Universe being passed around, but certain members being inaccessible to Human, consider using the protected modifier to limit access to members that inherit from the Universe class.
If you are okay with passing things in the constructor(like you recommended) you could pass any number of methods(delegates) to the human class so they can get the information any time they need, but it involves more complex implementation(I already did most of the work for you below)
If you're not sure what you want to do, and this doesn't need(for some specific business requirement) to work in the way you have described - Consider researching general Object Oriented Programing design patterns. There's a ton of resources online that can teach you OOP. The main topic I would recommend is the SOLID principles which will teach you a lot and be really useful. Thanks #flydog57 for mentioning this, as this would be more useful in the long run.
Interfaces
To visually hide/abstract the information unless explicitly accessed(casted) you can implement an IUniverse interface that defines only the members that you want publicly accessible.
// these would be the only accessible members
public interface IUniverse
{
Animal FindAnAnimal();
void UniverseAction();
}
public class Universe : IUniverse { ... }
public class Human
{
private readonly IUniverse universe;
public Human(IUniverse universe)
{
this.universe = universe;
}
}
Using interfaces to abstract which information should be available where can be really powerful! However, this does not prevent Human from casting the IUniverse to a Universe object explicitly and access it's other public members.
Protected Modifier
You can use the protected modifier (and a couple other ones) to completely remove access to information to other classes that don't meet certain requirements. For example the protected modifier would prohibit access to any protected members from any class that does not inherit from Universe. Make sure to checkout Access Modifiers for more information about the other options available to you.
public class Universe
{
protected List<Human> Humans { get; set; } = new();
protected List<Animal> Animals { get; set; } = new();
protected God AlphaOmega { get; set; }
public void UniverseAction()
{
//dosmthg
Console.WriteLine(nameof(UniverseAction));
}
public Animal FindAnAnimal()
{
//find an animal
Console.WriteLine(nameof(FindAnAnimal));
return Animals.FirstOrDefault();
}
}
public class Human
{
private readonly Universe universe;
public Human(Universe universe)
{
this.universe = universe;
}
//many Human things
public void CallingUniverseAction()
{
//How to?
universe.UniverseAction(); // works
UniverseAction.Humans.Clear(); // no access it's protected
}
public void CallingAnimalyStuff()
{
var animal = universe.FindAnAnimal(); // works
UniverseAction.Animals.Clear(); // no access it's protected
AlphaOmega.Kill(); // no access it's protected
}
}
Passing Delegates
You could for example pass delegates to the human to avoid passing around the Universe instance it self. Any method group is usually convertible to some form of Action or Func. Make sure to checkout Actions and Funcs for more information on both and how they can be passed around.
You can pass these around super simply for example:
public class Universe
{
public Human CreateHuman()
{
var newHuman = new Human(UniverseAction, FindAnAnimal);
Humans.Add(newHuman);
return newHuman;
}
}
public class Human
{
private readonly Action universeAction;
private readonly Func<Animal> animalyStuff;
public Human(Action universeAction, Func<Animal> animalyStuff)
{
this.universeAction= universeAction;
this.animalyStuff = animalyStuff;
}
//many Human things
public void CallingUniverseAction()
{
//How to?
universeAction?.Invoke();
}
public void CallingAnimalyStuff()
{
var animal = animalyStuff?.Invoke();
}
}
You could also implement a more robust, but more complex system if you need to pass a large amount of functions in the constructor like 20+. Passing a large number of things in a constructor is not a viable pattern, but it could work if you really wanted to, if you are required to do it to interop with legacy systems.
Here's a short snippet of what an implementation of that using reflection might look like.
public class Universe
{
protected List<Human> Humans { get; set; } = new();
protected List<Animal> Animals { get; set; } = new();
protected God AlphaOmega { get; set; }
public Human CreateHuman()
{
var newHuman = new Human(
(nameof(FindAnAnimal), (Func<Animal>)FindAnAnimal),
(nameof(UniverseAction), (Action)UniverseAction)
);
Humans.Add(newHuman);
return newHuman;
}
public void UniverseAction()
{
//dosmthg
}
public Animal FindAnAnimal()
{
//find an animal
}
}
public class Human
{
//many Human things
public void CallingUniverseAction()
{
Invoke(nameof(Universe.UniverseAction));
}
public void CallingAnimalyStuff()
{
var animal = Invoke(nameof(Universe.FindAnAnimal));
}
public Human(params (string Name, object Delegate)[] Methods)
{
foreach (var item in Methods)
{
InvokableReferences.Add(item.Name, item.Delegate);
}
}
private Dictionary<string, object> InvokableReferences = new();
public object Invoke(string DelegateName, params object[] Parameters)
{
if (InvokableReferences.ContainsKey(DelegateName))
{
object storedDelegate = InvokableReferences[DelegateName];
var delegateType = storedDelegate.GetType();
// check for the invoke method
var invokeMethod = delegateType.GetMethod(nameof(Invoke));
if (invokeMethod != null)
{
// check to see if it's an action or a func
var methodParams = invokeMethod.GetParameters();
if (methodParams is null)
{
// since there were no parameters then it is probably an Action or Func<T>
return invokeMethod.Invoke(storedDelegate, null);
}
// if it requires parameters it's probably a Action<T,..N> or Func<T...N,TResult>
// make sure we have enough parameters to invoke the method
if (methodParams.Length == Parameters.Length)
{
return invokeMethod.Invoke(storedDelegate, Parameters);
}
}
}
// if we failed to find the item return null;
return default;
}
}

C# OOP Cast interface parameter to concrete type

i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.

C# Passing current generic class instance to other class

lately I started to learn generics. I run into trouble with storing references to generic classes instances. As you can see, my class ListHandler can store references to specific type of BaseClass. I would love to register BaseClass instances by themselves, which is why I wanted to guarantee that they will use BaseParamClass by adding 'where'. Anyway - it does not compile.'This', does not know that T is actually BaseClassParam even with 'where' keyword in class. I don't know what is wrong here and I couldn't find answer anywhere. I would be grateful for tips/guides/solutions.
public class ListHandler
{
private List<BaseClass<BaseParamClass>> list;
public ListHandler()
{
list = new List<BaseClass<BaseParamClass>>();
}
public void Register(BaseClass<BaseParamClass> param)
{
list.Add(param);
}
}
public class BaseClass<T> where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this); //throws error
}
}
Why don't you make ListHandler generic as well?
public class ListHandler<T>
{
private List<BaseClass<T>> list;
public ListHandler()
{
list = new List<BaseClass<T>>();
}
public void Register(BaseClass<T> param)
{
list.Add(param);
}
}
public class BaseClass<T>
{
private ListHandler<T> listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler<T> listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Also, it seems strange to me to have BaseClass<T> contain a reference to a class that has a reference to BaseClass<T> itself.
I have another option for you.
Let's split the BaseClass<T> class into two with a non-generic base, like so:
public class BaseClass
{
protected ListHandler listHandler;
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
}
}
public class BaseClass<T> : BaseClass where T : BaseParamClass
{
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
: base(listHandler)
{
listHandler.Register(this); // Compiles nicely! Yay!
}
}
Now, the list inside ListHandler can be defined as private List<BaseClass> list;. That means there is no problem adding any BaseClass item to the list. We also can then define two methods for registering and fetching generic versions of the BaseClass<T> from the ListHandler. It would look like this:
public class ListHandler
{
private List<BaseClass> list;
public ListHandler()
{
list = new List<BaseClass>();
}
public void Register<T>(BaseClass<T> param) where T : BaseParamClass
{
list.Add(param);
}
public BaseClass<T> Fetch<T>() where T : BaseParamClass
{
return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
}
}
So, given a class public class FooParam : BaseParamClass { } I can write this code:
ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();
Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));
The result from this code is True is written to the console - which means I can successfully fetch the instance of BaseClass<FooParam> from the ListHandler.
Why your code doesn't compile
In order to fully understand why your code doesn't compile, you'll have to dive into covariance and contravariance, which is a big topic and hard to explain in an SO answer. It can be especially confusing if you've gotten to a point where inheritance polymorphism is second nature to you; the rules are just different enough to be make your head hurt.
Here is what is confusing--
You're used to doing this:
object a = new String(...);
But generics don't let you do this!
List<object> c = new List<string>(); //Compiler error
That's because those two Lists are not related the same way that object and string are related. One does not inherit from the other. Rather, they are different variants of a generic type definition. In the generic world, you can't assign one to the other. The same is true of this:
void Foo<T>() where T: BaseParamClass
{
BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}
In this example, T could be BaseParamClass or one of its derived types. They are not the same type. So to remain type-safe, the compiler has to disallow this assignment, and your Register call, which has the same type mismatch.
Standard ways around this
You need a covariant interface. These allow assignment from derived to base. So for example, while this is still illegal:
List<object> a = new List<string>(); //Compiler error
This is totally fine:
IEnumerable<object> e = new List<string>(); //Is OK
Because IEnumerable was declared to be covariant, like this:
interface IEnumerable<out T>
Which means it is can be assigned in this way. It works because using out also adds a compiler constraint to the interface: it can be used to retrieve stuff...
interface IEnumerable<out T>
{
T Item[int index];
}
...but it cannot accept anything:
interface IEnumerable<out T>
{
Add(T item); //Compiler error
}
These constraints are what allow generics to provide early-bound type safety while still allowing certain forms of (non-inheritance) polymorphism.
What I'd suggest
Based on your comment, it sounds like you just need a container (a stack, apparently) that can hold references to these BaseClass<T> instances. If you are following separation of concerns, the stack doesn't need to actually do anything with the T, other than store it and retrieve it, and to allow it to register itself.
Since that is a separate concern, make a separate interface.
And in the interest of keeping things simple, maybe avoid using generics completely for this bit.
One way to do it--
Create an interface that allows access to everything the stack needs to know about an item it is containing. For example, if the stack contains popups of various kinds, you may want to expose the popup's title.
interface IStackable
{
string Title { get; set; }
}
Now use it like this:
public class ListHandler
{
private readonly Dictionary<string, IStackable> list;
public ListHandler()
{
list = new Dictionary<string, IStackable>();
}
public void Register(IStackable item)
{
list.Add(item.Title, item);
}
}
public class BaseClass<T> : IStackable where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
public string Title { get; set; }
}
Unless there is some other requirement, you shouldn't need to make it any more complicated than that.
All you really need to do is add an interface. This works:
public class BaseParamClass
{
}
public class ListHandler
{
private List<IBase<BaseParamClass>> list;
public ListHandler()
{
list = new List<IBase<BaseParamClass>>();
}
public void Register(IBase<BaseParamClass> param)
{
list.Add(param);
}
}
public interface IBase<T> where T : BaseParamClass
{
T Param {get; }
}
public class BaseClass : IBase<BaseParamClass>
{
private ListHandler listHandler;
public BaseParamClass Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Working code on DotNetFiddle

How to use interface as a method parameter but still access non-interface methods?

I've spent hours trying to find a way to implement this and so far I haven't found a good solution, so I'm hoping someone could please help point me in the right direction.
I currently have a C# Winforms project that has an abstract base class with several child classes. Most of the methods are the same but each child class has a few additional methods specific to it.
I want to be able to declare a type of the class being used once and pass that type to all my other methods without having to manually check the type everywhere by going "If Class Type=A Do This Else If Class Type=B Do That, and so on".
The problem is that I need to pass the base class or interface to accomplish this. However, by doing so it means I can no longer access the properties or methods specific to the child classes and I don't know how to fix/workaround this.
Here's a simplified example of what I'm trying to do:
Interface and Class Structure
public interface IAnimal
{
string NameOfAnimal { get; set; }
void Eat();
}
public abstract class Animal : IAnimal
{
public abstract string NameOfAnimal { get; set; }
public abstract void Eat();
}
public class Bird : Animal
{
public Bird()
{
NameOfAnimal = "Bob the Bird";
NumberOfFeathers = 100;
}
// Interface members
public override string NameOfAnimal { get; set; }
public override void Eat()
{
System.Windows.Forms.MessageBox.Show("Eating like a Bird");
}
// Bird specific properties and methods
public int NumberOfFeathers { get; protected set; }
public string SomeOtherBirdSpecificProperty { get; protected set; }
public void Fly()
{
// Fly like a bird
}
}
public class Fish : Animal
{
public Fish()
{
NameOfAnimal = "Jill the Fish";
DoesFishHaveSharpTeeth = true;
}
// Interface members
public override string NameOfAnimal { get; set; }
public override void Eat()
{
System.Windows.Forms.MessageBox.Show("Eating like a Fish");
}
// Fish specific properties
public bool DoesFishHaveSharpTeeth { get; protected set; }
public string SomeOtherFishSpecificProperty { get; protected set; }
}
Main Form Code
private void button1_Click(object sender, EventArgs e)
{
IAnimal myCustomAnimal = null;
string animalTheUserSelected = "Bird";
// Only want to manually specify this once
switch (animalTheUserSelected)
{
case "Bird":
myCustomAnimal = new Bird();
break;
case "Fish":
myCustomAnimal = new Fish();
break;
default:
break;
}
DoSomethingWithACustomAnimal(myCustomAnimal);
}
private void DoSomethingWithACustomAnimal(IAnimal myAnimal)
{
// This works fine
MessageBox.Show(myAnimal.NameOfAnimal);
myAnimal.Eat();
// This doesn't work
MessageBox.Show(myAnimal.NumberOfFeathers);
myAnimal.Fly();
}
I understand why I'm having that issue in the main form code... the compiler doesn't know which type of animal is being passed to it yet so it doesn't know what to show. However, I don't know what I should do to fix this.
I've tried:
Putting all the animal-specific properties in the interface. This works but violates several OOP principles. A fish doesn't have feathers, etc. so these specific properties don't belong there.
Manually checking the type everywhere by going something like "If Type=Fish do abc Else If Type=Bird do def". This also works but violates the DRY principle because I'm repeating myself everywhere. Also with a lot of methods using animals, this will be a nightmare to maintain in the future.
Explicitly casting IAnimal to a specific animal like ((Bird)myCustomAnimal).NumberOfFeathers. This also works but I don't know what cast to use at compile-time. This won't be known until the user selects an animal at run-time.
So I'm just wondering how I can solve this issue?
More specifically, I'm wondering how I can re-design the above code so that I can both:
A) Explicitly declare a type of animal only once and pass that type everywhere (without having to do lots of manual checks in every method to see what type it is before doing something with it)
and also
B) Somehow still have a way to manually access the animal-specific properties like someBird.NumberOfFeathers when I need to.
Any ideas?
It really depends on exactly what you are trying to do and what you are hoping to achieve. All the things you've tried so far are possible approaches, but without more context it's hard to give a general answer. It depends on what the right level of abstraction is for what you are trying to do.
One thing to remember is that you can have a class implement as many interfaces as you need. So you could do something like:
public interface IAnimal
{
string NameOfAnimal { get; set; }
void Eat();
}
public interface IFly
{
void Fly();
}
public interface IHaveFeathers
{
int NumberOfFeathers { get; set; }
}
Then you Bird class can be:
public Bird : Animal, IFly, IHaveFeathers
{
// implementation
}
And now in a method you can do something like:
private void DoSomethingWithACustomAnimal(IAnimal myAnimal)
{
// This works fine
MessageBox.Show(myAnimal.NameOfAnimal);
myAnimal.Eat();
var feathered = myAnimal as IHaveFeathers;
if (feathered != null)
{
MessageBox.Show(feathered.NumberOfFeathers);
}
var flier = myAnimal as IFly;
if (flier != null)
{
flier.Fly();
}
}
The other thing to think about is how to abstract what you need to a higher level. So you need to Fly, but why? What happens with the Animal that can't fly? By Fly are you really just trying to Move? Then perhaps you could do:
public interface IAnimal
{
string NameOfAnimal { get; set; }
void Eat();
void Move();
}
And in your Bird you can do this:
public Bird : Animal, IFly, IHaveFeathers
{
public override void Move()
{
Fly();
}
public void Fly()
{
// your flying implementation
}
// rest of the implementation...
}
One solution would be to use the visitor pattern to define the operations you want to perform on your animal instances.
First you would define a visitor interface which provides a method for each type of animal you have in your hierarchy.
public interface IAnimalVisitor
{
void VisitBird(Bird bird);
void VisitFish(Fish fish);
}
And then you would need to modify your animal classes and interfaces to include a method which accepts a visitor, like so:
public interface IAnimal
{
string NameOfAnimal { get; set; }
void Accept(IAnimalVisitor visitor);
}
Your actual animal classes now look something like this:
public class Bird : IAnimal
{
public Bird()
{
NameOfAnimal = "Bob the Bird";
NumberOfFeathers = 100;
}
public string NameOfAnimal { get; set; }
public int NumberOfFeathers { get; protected set; }
public void Accept (IAnimalVisitor visitor)
{
visitor.VisitBird(this);
}
}
public class Fish : IAnimal
{
public Fish()
{
NameOfAnimal = "Jill the Fish";
DoesFishHaveSharpTeeth = true;
}
public string NameOfAnimal { get; set; }
public bool DoesFishHaveSharpTeeth { get; protected set; }
public void Accept (IAnimalVisitor visitor)
{
visitor.VisitFish(this);
}
}
Now for anything you want to do with each of your animals you will need to define an implementation of the IAnimalVisitor interface. In your example you displayed message boxes that showed information about the animal so an implementation of the IAnimalVisitor interface that does that could look like this:
public class AnimalMessageBoxes : IAnimalVisitor
{
private void VisitAnimal(IAnimal animal)
{
MessageBox.Show(animal.NameOfAnimal);
}
public void VisitBird(Bird bird)
{
visitAnimal(bird);
MessageBox.Show(bird.NumberOfFeathers);
}
public void VisitFish(Fish fish)
{
visitAnimal(fish);
MessageBox.Show(fish.DoesFishHaveSharpTeeth);
}
}
Now you just need to pass your visitor to your animal and the correct information will be displayed. Your event handling code now looks something like this:
string animalTheUserSelected = "Bird";
IAnimal myCustomAnimal = null;
switch (animalTheUserSelected)
{
case "Bird":
myCustomAnimal = new Bird();
break;
case "Fish":
myCustomAnimal = new Fish();
break;
default:
break;
}
AnimalMessageBoxes msgBoxes = new AnimalMessageBoxes();
myCustomAnimal.Accept(msgBoxes);
If you want to do something else to your animal instances (save them to a file, generate a UI, play sounds...) you just need to define a new IAnimalVisitor implementation that provides your desired behaviour.
For the sake of balance I will say that this might not be an appropriate design as it adds some additional complexity; each 'operation' requires you to implement a visitor and the addition of another animal to your hierarchy requires you to update your visitor interface and all of it's implementations to account for the new case.
Depending on your point of view this can be either good or bad. Some consider the points above to be bad and a reason to avoid the visitor pattern and to use the other methods already suggested. Others (like me) consider the points above to be a good thing; your code will now only compile when you provide an implementation for each animal in your hierarchy and your operations are separated into small, dedicated classes.
My suggestion would be to try the SSCCE I have provided and research the visitor pattern further to decide if this solution is acceptable for your requirements.
I understand, what you are trying to achive, but your approach is just wrong.
Think it this way: does your "Main" class/form realy need to know if there is a bird or a dog? The answer is "NO". There are some common properties which you exposed via an interface (i suggest using a base class here!). Everything else is specific to the given animal. The easiest approach is extending your interface with a DoAnimalSpecificStuff() method - which would perform the specific opperations.
When it comes to presentation, you should take a look at the MVP and MVVM Patterns.
P.S. use a Factory Pattern for animal creation!
You have to explicitly cast the IAnimal object to specific type, if you want to access specific properties/methods.
You can use as operator and then check if the cast was successful like:
Bird b = myAnimal as Bird;
if(b != null)
{
MessageBox.Show(b.NumberOfFeathers);
}

Declare a generic type as property of an interface?

I've a Generic type, which is used to give some meta data on an object to persist:
public class PersistedElementDefinition<T> where T: IPersistedObject{
List<PersistedPropertyDefinition<T>> PropertiesToPersist {get;set;}
}
public class PersistedPropertyDefinition<T> where T: IPersistedObject{
public Func<T, object> PropertyGetter{get;set;}
public Action<T, object> PropertySetter {get;set;}
}
and I've my IPersistedObject which can give his definition
public interface IPersistedObject{
PersistedElementDefinition<TypeOfTheImplementingType> Definition {get;}
}
The idea is that if I implement IPersistedObject I should implement it like this:
public class MyPersistedObject:IPersistedObject{
PersistedElementDefinition<MyPersistedObject> Definition{get;}
}
When I persist my class have the following thing:
I can't do the following:
public interface IPersistedObject<T>{
PersistedElementDefinition<T> Definition {get;}
}
because:
It would allow to have a MyPersistedObject<SomeOtherObject
At some point I receive an object, and I should be able to see if it implements the IPersistedObject and do some custom action with it.
For the 2, here is an example of what kind of issue I'm facing if I've a Generic interface:
public void Persist<T>(T objectToPersist)where T:IPersistedObject{
...
foreach(PersistedPropertyDefinition<T> property in objectToPersist.PropertiesToPersist){
object objectToSerialize = property.ObjectGetter(objectToPersist);
if(objectToSerialize is IPersistedObject<___Don't know how to put something generic here___>){
Persist((IPersistedObject<___Don't know how to put something generic here___>)objectToSerialize);
}
}
...
}
Is there a possibility in c# to declare an interface with a generic property of the implementing type?
You can use the curiously recurring template pattern to lock this down a bit further. It isn't bulletproof, but assuming you're not a masochist, and you don't mind the fact that it is theoretically possible to create nonsensical implementations of the interface that violate the invariants you are trying to guarantee, you can do this:
public interface IPersistedObject<T> where T : IPersistedObject<T>
{
PersistedElementDefinition<T> Definition {get;}
}
public class PersistedElementDefinition<T> where T: IPersistedObject<T>
{
...
}
public class MyPersistedObject : IPersistedObject<MyPersistedObject>
{
// Here, you are forced to implement a PersistedElementDefinition<MyPersistedObject>,
// which presumably is the reason behind this whole song and dance
PersistedDefinition<MyPersistedObject> Definition { get; }
}
The problem with this, as you noticed at the outset, is that you could simply define public class MyPersistedObject : IPersistedObject<MyOtherPersistedObject>, and end up breaking the contract you are trying to cobble together, which in plain words is the following:
A persisted object must have a gettable definition that is a persisted element definition of its own type
The C# type system is simply not equipped to handle this elegantly. My advice is to get out early, change to object or dynamic where possible and learn to live with the loss of certain compile time guarantees.
Assuming you're willing to sacrifice some compile time safety, you could do things like so:
class Program
{
static void Main(string[] args)
{
var mpo = new MyPersistedObject();
var ptp = mpo.Definition.PropertiesToPersist;
}
}
public class PersistedElementDefinition<T> where T : IPersistedObject
{
private readonly List<PersistedPropertyDefinition<T>> _propsToPersist = new List<PersistedPropertyDefinition<T>>();
public List<PersistedPropertyDefinition<T>> PropertiesToPersist
{
get { return _propsToPersist; }
}
}
public class PersistedPropertyDefinition<T> where T : IPersistedObject
{
public Func<T, object> PropertyGetter { get; set; }
public Action<T, object> PropertySetter { get; set; }
}
public interface IPersistedObject
{
dynamic Definition { get; }
}
public class MyPersistedObject : IPersistedObject
{
private readonly PersistedElementDefinition<MyPersistedObject> _definition = new PersistedElementDefinition<MyPersistedObject>();
public dynamic Definition { get { return _definition; } }
}

Categories