在MEF中以通用方法转换类

DIl*_*d K 5 .net c# generics reflection mef

我有一些类和接口:

interface IAnimal { }
interface ILiveInZoo { }
class Cat : IAnimal, ILiveInZoo { }
Run Code Online (Sandbox Code Playgroud)

另外,我有一些方法和通用方法:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个用例:

Context context = new Context();
var cat = context.GetWhoLivesInZoo("Cat");
if (cat is IAnimal animal)
{
   context.GiveFood(animal);
}
Run Code Online (Sandbox Code Playgroud)

如您在GiveFoodmetod 中所见,我正在使用MEF。在使用情况下,当我投catIAnimal,在GiveFoodtypeof(T)IAnimal不会Cat。第一个问题是:cat变量的实例是Cat类。为什么当我投放时typeof(T)会成为IAnimal?我的问题是,当我投catIAnimal界面,GiveFood方法,GetExports相关方法返回方法IAnimalCat类。我找到解决此问题的解决方案,它使用反射:

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 });
}
Run Code Online (Sandbox Code Playgroud)

现在typeof(T)Cat类,GiveFood我可以得到与Cat类相关的方法。是否有另一种方法(不使用反射)来解决此问题?

小智 0

一个简单易用的解决方案可能是使用动态

Context context = new Context();
var cat = context.GetWhoLivesInZoo("Cat");
if (cat is IAnimal animal)
{
    context.GiveFood((dynamic)animal);
}
Run Code Online (Sandbox Code Playgroud)

但请注意,它dynamic在内部使用反射(通过缓存来提高性能)。因此,如果您真的想避免反射,另一个答案中描述的访问者模式可能是正确的选择。