我应该尝试隐藏 IoC 容器(如果是的话,有什么提示)吗?
我正在构建一个 CMS,它有许多扩展点(数据/内容类型、插件、宏、主题),其中一些扩展需要注册服务。到目前为止,扩展仅依赖于“MyProject.Core”库,如果它们不依赖于任何特定的 IoC 框架,那就太好了。现在我在想是否应该构建另一个层来隐藏 IoC 特定的注册。问题是我需要一些高级功能。
例如,“Data/ContentType”服务的 NHibernate 实现(温莎城堡风格)
container.Register(Component.For<IPageRepository>().ImplementedBy<NHPageRepository>());
container.Register(Component.For<ISessionFactory>().Instance(NHibernateHelper.CreateSessionFactory()));
container.Register(Component.For<ISession>().UsingFactoryMethod(c => c.Resolve<ISessionFactory>().OpenSession()).LifeStyle.PerWebRequest);
第三行是“硬行”。我可以制作一个类似的接口,
interface IMyContainer
{
Register<TService>(Func<IMyContainer,TService> factoryMethod)
Register<TService>(Func<IMyContainer,TService> factoryMethod, LifeStyle lifeStyle)
// ...
}
但是将这个注册(我的 IoC 抽象)“翻译”
public class NHInstaller : IInstaller
{
public void Install(IMyContainer container)
{
container.Register<ISession>(c => c.Resolve<ISessionFactory>().OpenSession(), LifeStyle.PerRequest);
}
}
到这个(Windsor)
container.Register(Component.For<ISession>().UsingFactoryMethod(c => c.Resolve<ISessionFactory>().OpenSession()).LifeStyle.PerWebRequest);
可能会非常困难。
那么,我应该尝试进行这种抽象吗?有什么有用的资源吗? 或者我应该选择一个 IoC 容器并坚持使用它?
我还可以将现有工具(Castle Windsor 或 Ninject)的源代码作为我的库的一部分,但我并不真正理解这些许可证。我可以这样做吗?我可以更改命名空间和类名以适应我的应用程序的结构吗?我将发布源代码,我并不关心许可证是什么。
I'm building a CMS and it has many extension points (Data/ContentTypes, Plugins, Macros, Themes) and some of those extensions need to register services. So far extensions only depend on 'MyProject.Core' library and it would be nice if they wouldn't be dependant on any specific IoC framework. Now I'm thinking if I should build another layer to hide IoC specific registrations. The problem is that I need some advanced functionality.
E.g. NHibernate implementation of 'Data/ContentType' services (Castle Windsor style)
container.Register(Component.For<IPageRepository>().ImplementedBy<NHPageRepository>());
container.Register(Component.For<ISessionFactory>().Instance(NHibernateHelper.CreateSessionFactory()));
container.Register(Component.For<ISession>().UsingFactoryMethod(c => c.Resolve<ISessionFactory>().OpenSession()).LifeStyle.PerWebRequest);
Third line is the "hard one". I could make an interface like
interface IMyContainer
{
Register<TService>(Func<IMyContainer,TService> factoryMethod)
Register<TService>(Func<IMyContainer,TService> factoryMethod, LifeStyle lifeStyle)
// ...
}
but "translating" this registration (my IoC abstraction)
public class NHInstaller : IInstaller
{
public void Install(IMyContainer container)
{
container.Register<ISession>(c => c.Resolve<ISessionFactory>().OpenSession(), LifeStyle.PerRequest);
}
}
to this (Windsor)
container.Register(Component.For<ISession>().UsingFactoryMethod(c => c.Resolve<ISessionFactory>().OpenSession()).LifeStyle.PerWebRequest);
could be quite hard.
So, should I try to make that abstraction? Any helpful resources?
Or should I just pick a IoC container and stick with it?
I could also make source code of an existing tool (Castle Windsor or Ninject) a part of my library, but I don't really understand those licenses. Can I do that? Can I change namespaces and class names to fit the structure of my app? I'm going to release the source code and I don't really care what the license is going to be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这取决于你所说的“隐藏”是什么意思。最佳做法是应用程序中只有一个位置(组合根 )了解 IoC 容器。坚持好莱坞原则 - 避免拥有多个了解 IoC 容器的类。换句话说,不要传递容器;如果非根类需要创建其他对象,则将工厂注入其中。
如果您
正在编写一个框架并且希望允许消费者插入他们选择的IoC容器框架,您可以使用通用服务定位器库。对于大多数项目来说,这可能有点矫枉过正。 (请参阅 Mark Seemann 的优秀链接了解我更改措辞的原因) 。It depends on what you mean by "hide." Best practice is that only one place in your application (the Composition Root) knows about the IoC container. Stick to the Hollywood Principle - avoid having multiple classes that know about the IoC container. In other words don't pass the container around; if a non-root class needs to create other objects then inject a factory into it.
If you
're writing a framework andwant to allow consumers to plug in their IoC container framework of choice, you could use the Common Service Locator library. That is likely overkill for most projects. (See Mark Seemann's excellent link for the reason I changed the wording).简短的回答 - 不,抽象是没有用的,你会浪费雇主的钱。请使用 安装程序 对注册进行分区。
Short answer - no, the abstraction is useless, you'd be wasting your employer's money. Use Installers to partition the registration instead.