I have some classes and interface:
interface IAnimal { }
interface ILiveInZoo { }
class Cat : IAnimal, ILiveInZoo { }
Also, I have some methods and generic methods:
class Context
{
private static CompositionContainer Container = null;
public ILiveInZoo GetWhoLivesInZoo(string name)
{
if (name == "Cat")
return new Cat();
return null;
}
public void GiveFood<T>(T animal) where T : IAnimal
{
var methods = Container.GetExports<Action<T, EventArgs>, AttributeMetadata>();
//execute methods
}
}
And here is a use case:
Context context = new Context();
var cat = context.GetWhoLivesInZoo("Cat");
if (cat is IAnimal animal)
{
context.GiveFood(animal);
}
As you can see in GiveFood
metod I'm using MEF
. In use case when I cast cat
to IAnimal
, in GiveFood
method typeof(T)
will be IAnimal
not Cat
. First question is:
Instance of cat
variable is Cat
class. Why when I cast it, typeof(T)
will be IAnimal
?
My problem is when I cast cat
to IAnimal
interface, in GiveFood
method, GetExports
method returns method related to IAnimal
not to Cat
class. I found solution to fix that issue, it is using reflection:
Context context = new Context();
var cat = context.GetWhoLivesInZoo("Cat");
if (cat is IAnimal animal)
{
MethodInfo method = typeof(Context).GetMethod(nameof(Context.GiveFood));
MethodInfo generic = method.MakeGenericMethod(animal.GetType());
generic.Invoke(context, new object[] { animal });
}
Now typeof(T)
is Cat
class and in GiveFood
I can get methods related to Cat
class. Is there another way (without using reflection) to solve this issue?
A simple and easy to use Solution could be to use dynamic:
Context context = new Context();
var cat = context.GetWhoLivesInZoo("Cat");
if (cat is IAnimal animal)
{
context.GiveFood((dynamic)animal);
}
Do note however that dynamic
uses Reflection internally (with caching to make it a little more performant). So if you really want to avoid Reflection, the Visitor Pattern described in the other answer is probably the way to go.