以下是我希望它如何运作
container.GetButDoNotCreate<T>(); // should throw (or can return null) if container doesn't contain an instance matching the contract
var x = container.GetExportedValue<T>();
var y = container.GetButDoNotCreate<T>(); // should return the object created in previous step
Assert.That(x).IsSameAs(y);
不同之处在于,如果容器不包含实例,则此方法不会创建实例。它是一个纯粹的get,如果它存在于容器中,请将此对象告诉我。 我需要它用于我的测试,我不希望测试代码在生产容器中创建对象(如果它们没有被创建)只使用现有的对象。只有生产代码才能在容器中添加/删除对象。
发布到MEF codeplex forum但没有回复。所以希望SO上的某个人可能有答案。 此外,如果我需要将该函数编写为扩展方法......那也可以作为答案。
答案 0 :(得分:1)
这是我的解决方案。起初我尝试创建一个扩展方法。我尝试了几件事,阅读了文档并探讨了容器和目录上的可用属性,事件和方法,但我无法做任何事情。
在考虑问题后,我能想出解决方案的唯一方法是创建一个基于CompositionContainer的派生容器,并实现GetButDoNotCreate方法。
更新:我发布后发现该解决方案仅适用于您发布的简单示例,其中仅使用GetExportedValue检索零件简单零件。除非您将容器用作没有[Import]的零件的简单服务定位器,否则在创建具有[Import]的零件时将无法执行。
以下是实施:
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
namespace GetButNotCreate
{
public class CustomContainer : CompositionContainer
{
private List<Type> composedTypes = new List<Type>();
public CustomContainer(ComposablePartCatalog catalog)
: base(catalog)
{
}
public new T GetExportedValue<T>()
{
if (!composedTypes.Contains(typeof(T)))
composedTypes.Add(typeof(T));
return base.GetExportedValue<T>();
}
public T GetButDoNotCreate<T>()
{
if (composedTypes.Contains(typeof(T)))
{
return base.GetExportedValue<T>();
}
throw new Exception("Type has not been composed yet.");
}
}
}
它的工作原理是覆盖GetExportedValue方法以跟踪到目前为止已组成的类型,然后使用它来检查GetButNotCreate中的类型组合。我抛出了你问题中提到的异常。
当然,您可能需要覆盖GetExportedValue的重载(除非您不使用它们,但即便如此,我仍会为了安全而覆盖它们)并且如果您使用该类,可能会添加其他构造函数和内容。在这个例子中,我做了最低限度的工作。
以下是测试新方法的单元测试:
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace GetButNotCreate
{
public interface IInterface { }
[Export(typeof(IInterface))]
public class MyClass : IInterface
{
}
[TestClass]
public class UnitTest1
{
[TestMethod]
[ExpectedException(typeof(Exception), "Type has not been composed yet.")]
public void GetButNotCreate_will_throw_exception_if_type_not_composed_yet()
{
var catalog = new AssemblyCatalog(typeof(UnitTest1).Assembly);
CustomContainer container = new CustomContainer(catalog);
container.ComposeParts(this);
var test = container.GetButDoNotCreate<IInterface>();
}
[TestMethod]
public void GetButNotCreate_will_return_type_if_it_as_been_composed()
{
var catalog = new AssemblyCatalog(typeof(UnitTest1).Assembly);
CustomContainer container = new CustomContainer(catalog);
container.ComposeParts(this);
var x = container.GetExportedValue<IInterface>();
var y = container.GetButDoNotCreate<IInterface>();
Assert.IsNotNull(y);
Assert.AreEqual(x, y);
}
}
}
它表明如果从未导出类型,GetButNotCreate将抛出异常,如果已导入该类型,它将返回此类型。
我无法在任何地方找到任何钩子(不使用反射)来查看MEF是否已经组成了一个部件,所以这个CustomContainer解决方案将是我最好的选择。
答案 1 :(得分:0)
我认为值得在Container上拥有自己的包装器。像IContainerWrapper之类的东西,并在代码中的任何地方使用它。
实现这一目标:
如果您有通常的单元测试,您只需注入另一个适合您需要的包装实例。
如果要访问生产容器,但具有上述行为,则可以在生产包装器实现中使用预处理器指令。