MEF 2,实现 class 的通用导入
MEF 2, Generic Import with implementing class
我正在尝试利用泛型和 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 was
unhandled Message=The composition remains unchanged. The changes
were rejected because of the following error(s): The composition
produced a single composition error. The root cause is provided below.
Review the CompositionException.Errors property for more detailed
information.
1) No exports were found that match the constraint:
ContractName MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
RequiredTypeIdentity MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
Resulting in: Cannot set import 'MEFGeneric.Program.TheAnimalCatcher (ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)")' on
part 'MEFGeneric.Program'. Element:
MEFGeneric.Program.TheAnimalCatcher
(ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)") -->
MEFGeneric.Program
请注意 IAnimalCatcher<IAnimal>
会注册,但这并不能让我将捕狗器限制为狗。
有没有办法通过导入来解决这个问题,或者我的设计有缺陷,我应该以不同的方式实现 DogCatcher 吗?
MEF 正在寻找导出 IAnimalCatcher<IAnimal>
的类型。您有 DogCatcher
导出 IAnimalCatcher<Dog>
,因此这不是合适的候选者。将 DogCatcher
的导出更改为 IAnimalCatcher<IAnimal>
不是解决方案,因为 您无法将 IAnimalCatcher<Dog>
分配给 IAnimalCatcher<IAnimal>
。
如果您能够进行分配,则可以通过设置 IAnimalCatcher.AnimalCaught
属性 的值将 DogCatcher
中的 AnimalCaught
分配给 Cat
类型 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
中删除 setter,则可以使 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; }
}
我正在尝试利用泛型和 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 was unhandled Message=The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint: ContractName MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal) RequiredTypeIdentity MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)
Resulting in: Cannot set import 'MEFGeneric.Program.TheAnimalCatcher (ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)")' on part 'MEFGeneric.Program'. Element: MEFGeneric.Program.TheAnimalCatcher (ContractName="MEFGeneric.IAnimalCatcher(MEFGeneric.IAnimal)") --> MEFGeneric.Program
请注意 IAnimalCatcher<IAnimal>
会注册,但这并不能让我将捕狗器限制为狗。
有没有办法通过导入来解决这个问题,或者我的设计有缺陷,我应该以不同的方式实现 DogCatcher 吗?
MEF 正在寻找导出 IAnimalCatcher<IAnimal>
的类型。您有 DogCatcher
导出 IAnimalCatcher<Dog>
,因此这不是合适的候选者。将 DogCatcher
的导出更改为 IAnimalCatcher<IAnimal>
不是解决方案,因为 您无法将 IAnimalCatcher<Dog>
分配给 IAnimalCatcher<IAnimal>
。
如果您能够进行分配,则可以通过设置 IAnimalCatcher.AnimalCaught
属性 的值将 DogCatcher
中的 AnimalCaught
分配给 Cat
类型 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
中删除 setter,则可以使 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; }
}