MEF——我似乎在这里遗漏了一些东西
所以,我正在尝试 MEF——有点尝试经典的 IoC 东西——注入一个日志记录类。 我让它工作了,但它没有按照我预期的方式工作。你能告诉我哪里偏离了轨道吗?
我认为我的问题是我错误地引导 MEF。我期望导出一个记录器,然后导入它以将其注入到任何想要使用它的类中。
我发现,对于任何想要使用它的类,我必须新建一个容器,加载目录,然后调用 ComposeParts()。 (这实际上比仅仅调用 MyEventLogFactory.GetEventLog() 困难得多)。 (我预计必须在程序初始化时引导 MEF 一次,但我似乎必须为导入的每个类执行此操作)
这是我的引导代码(在控制台应用程序的启动中):
static void Main(string[] args)
{
InitMefContainer();
var test = new TestHarness();
test.RunTest();
Console.ReadLine();
}
private static void InitMefContainer()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(EventLogFactory).Assembly));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
var container = new CompositionContainer(catalog);
container.ComposeParts();
_Container = container;
}
然后我的 TestHarness 类看起来像this:
public class TestHarness
{
[Import(typeof(IEventLog))]
public IEventLog EventLog { get; set; }
public void RunTest()
{
// did not expect to need to do this, but EventLog is null if I don't
Program._Container.ComposeParts(this);
this.EventLog.Write(some test event stuff);
}
}
我的问题是 EventLog 始终为空。 -- 除非,我重复 Program.Main 执行的所有 MefInitialization 代码(或者,如果我将 Program 创建的容器设为公共静态,我可以调用 _Container.ComposeParts(this);
所以,我的问题:什么是正确的引导 MEF 以满足我的所有导入的方式?通常的做法是使用公共静态容器并调用 Container.Compose(this) (或使用 AStaticContainer.GetExportedValue 之类的)就像你会在我的所有类中使用 ServiceLocator.GetService() 一样——我绝对没有在任何示例代码中看到这一点。
So, I'm playing around with MEF -- kind of trying a classic IoC thing -- injecting a logging class.
I have it working, but it is not working the way I expected it to work. Can you tell me where I'm off track?
I think that my problem is that I'm bootstrapping MEF incorrectly. I expected to Export a logger, and Import it to inject it into any class that wanted to use it.
What I'm finding is that for any class that wants to use it, I have to new up a container, load the catalogs, and call ComposeParts(). (which is actually a lot harder than just calling MyEventLogFactory.GetEventLog()). (I expected to have to bootstrap MEF once, on program init, but I seem to have to do it for every class that has in import)
Here's my bootstrap code (in the startup of a Console app):
static void Main(string[] args)
{
InitMefContainer();
var test = new TestHarness();
test.RunTest();
Console.ReadLine();
}
private static void InitMefContainer()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(EventLogFactory).Assembly));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
var container = new CompositionContainer(catalog);
container.ComposeParts();
_Container = container;
}
Then my TestHarness class looks like this:
public class TestHarness
{
[Import(typeof(IEventLog))]
public IEventLog EventLog { get; set; }
public void RunTest()
{
// did not expect to need to do this, but EventLog is null if I don't
Program._Container.ComposeParts(this);
this.EventLog.Write(some test event stuff);
}
}
My problem is that EventLog is always null. -- Unless, I repeat all of the MefInitialization code that Program.Main executed (or, if I make the container that Program created a public static, I can call _Container.ComposeParts(this);
So, my question: what is the right way to bootstrap MEF so that it satisfies all of my imports? Is it common practice to have a public static container and call Container.Compose(this)? (or to use AStaticContainer.GetExportedValue, sort of like you would use ServiceLocator.GetService()? inside all of my classes -- I definitely have not seen that in any sample code out there.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我尝试在引导程序中尽可能多地通过容器注入。
我认为是这样的:
这会向容器询问 TestHarness 实例,并且它会在为您实例化它时导入任何依赖项。
至于使用单例、静态、服务定位器或任何使其可用的方法来保留对容器的引用,当您需要要求它们为您解析类型时,这与大多数其他 IoC 框架的原理类似。
I try to have as much as possible injected by the container in the bootstrap.
I think something like this:
This asks the container for the TestHarness instance, and it will import any dependencies as it instantiates it for you.
As far as keeping a reference to the container around, using singleton, static, servicelocator or whatever method of making it available, that is a similar principle to most other IoC frameworks when you need to ask them to resolve a type for you.