我正在尝试利用Generics with和MEF解决方案的优势,但是我正在努力让事情注册。 (上午使用MEF 2,.Net 4.51)。

这是我要工作的类和接口的简化版本:

public interface IAnimal
{
    string Speak();
}

public interface IAnimalCatcher<T> where T : IAnimal
{
    string WhatICatch();
    T AnimalCaught { get; set; }
}

[Export(typeof(IAnimal))]
public class Dog : IAnimal
{
    public string Speak()
    {
        return "Woof";
    }
}

//[Export(typeof(IAnimalCatcher<IAnimal>))]
//[Export(typeof(IAnimalCatcher<Dog>))]
public class DogCatcher: IAnimalCatcher<Dog>
{
    public string WhatICatch()
    {
        return "Dogs";
    }

    public Dog AnimalCaught { get; set; }
}


以及组成代码的代码:

 public class Program
    {

        private CompositionContainer _container;

        [Import(typeof(IAnimal))]
        public IAnimal TheAnimal;


        [Import(typeof(IAnimalCatcher<>))]
        public IAnimalCatcher<IAnimal> TheAnimalCatcher;

         public Program()
        {
            var catalog = new AggregateCatalog();

            catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));

            _container = new CompositionContainer(catalog);
            this._container.ComposeParts(this);

        }

    }


我无法使Dog Class正确导出和导入。我尝试了几种组合,但均未成功(在课程上方进行了评论)。

错误如下:


  System.ComponentModel.Composition.ChangeRejectedException原为
  未处理的消息=组成保持不变。变化
  由于以下错误而被拒绝:组成
  产生了单个成分错误。根本原因在下面提供。
  查看CompositionException.Errors属性以获取更多详细信息
  信息。
  
  1)未找到符合约束条件的出口:
    ContractName MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
    RequiredTypeIdentity MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
  
  结果:无法在上设置导入'MEFGeneric.Program.TheAnimalCatcher(ContractName =“ MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)”)'
  部分“ MEFGeneric.Program”。元件:
  MEFGeneric.Program.TheAnimalCatcher
  (ContractName =“ MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)”)->
  MEF通用程序


请注意,IAnimalCatcher<IAnimal>将注册,但这不能让我将捕犬器限制为狗。

有没有一种方法可以通过导入解决此问题,或者我的设计存在缺陷,我应该以不同的方式实现DogCatcher吗?

最佳答案

MEF正在寻找一种导出IAnimalCatcher<IAnimal>的类型。您有DogCatcher可以导出IAnimalCatcher<Dog>,因此不合适。将DogCatcher的导出更改为IAnimalCatcher<IAnimal>不是解决方案,因为您无法将IAnimalCatcher<Dog>分配给IAnimalCatcher<IAnimal>

如果能够进行分配,则可以通过设置类型为AnimalCaughtDogCatcher属性的值来将CatIAnimalCatcher.AnimalCaught分配给IAnimal。您不希望DogCatcher捕获Cat,因此编译器将不允许它。

解决方案是更改DogCatcher,以便它实现IAnimalCatcher<IAnimal>而不是IAnimalCatcher<Dog>

[Export(typeof(IAnimalCatcher<IAnimal>))]
public class DogCatcher: IAnimalCatcher<IAnimal>
{
    public string WhatICatch()
    {
        return "Dogs";
    }

    public IAnimal AnimalCaught { get; set; }
}


不幸的副作用是,您现在允许任何人修改被DogCatcher捕获的动物,使其成为Cat

但是还有另一种选择。如果可以从AnimalCaught中删除​​设置器,则可以使IAnimal类型参数为协变变量(out修饰符):

public interface IAnimalCatcher<out T> where T : IAnimal
{
    string WhatICatch();
    T AnimalCaught { get; }
}


这使得将IAnimalCatcher<Dog>分配给IAnimalCatcher<IAnimal>合法:

[Export(typeof(IAnimalCatcher<IAnimal>))]
public class DogCatcher: IAnimalCatcher<Dog>
{
    public string WhatICatch()
    {
        return "Dogs";
    }

    public Dog AnimalCaught { get; private set; }
}

关于c# - MEF 2,具有实现类的常规导入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32797571/

10-11 02:19