【问题标题】:MEF 2, Generic Import with implementing classMEF 2,具有实现类的通用导入
【发布时间】:2015-09-26 13:10:58
【问题描述】:

我正在尝试利用泛型和 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 类正确导出和导入。我尝试了几种组合但没有成功(在课程上方评论)。

错误如下:

System.ComponentModel.Composition.ChangeRejectedException 是 unhandled Message=组合保持不变。变化 由于以下错误而被拒绝: 产生了一个单一的构图错误。下面提供了根本原因。 查看 CompositionException.Errors 属性以获取更多详细信息 信息。

1) 未找到与约束匹配的导出: 合同名称 MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal) 必需的TypeIdentity MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)

导致:无法设置 import 'MEFGeneric.Program.TheAnimalCatcher (ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)")' on 部分'MEFGeneric.Program'。元素: MEFGeneric.Program.TheAnimalCatcher (ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)") --> MEFGeneric.程序

请注意,IAnimalCatcher&lt;IAnimal&gt; 会注册,但这并不能让我将狗捕手限制在狗身上。

有没有办法通过导入来解决这个问题,或者我的设计有缺陷,我应该以不同的方式实现 DogCatcher?

【问题讨论】:

    标签: c# generics mef


    【解决方案1】:

    MEF 正在寻找导出IAnimalCatcher&lt;IAnimal&gt; 的类型。你有 DogCatcher 导出 IAnimalCatcher&lt;Dog&gt; 所以这不是一个合适的候选人。将DogCatcher 的导出更改为IAnimalCatcher&lt;IAnimal&gt; 不是解决方案,因为您不能将IAnimalCatcher&lt;Dog&gt; 分配给IAnimalCatcher&lt;IAnimal&gt;

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

    解决方案是更改DogCatcher,使其实现IAnimalCatcher&lt;IAnimal&gt; 而不是IAnimalCatcher&lt;Dog&gt;

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

    不幸的副作用是您现在允许任何人修改DogCatcher 捕获的动物以说出Cat

    但还有另一种选择。如果您可以从AnimalCaught 中删除setter,您可以使IAnimal 类型参数协变(out 修饰符):

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

    这使得将IAnimalCatcher&lt;Dog&gt; 分配给IAnimalCatcher&lt;IAnimal&gt; 合法:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多