C# 类库中的 IoC。在哪里引导
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10191060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
IoC in class library. Where to bootstrap
提问by Patrick
I'm using a class library that can be reused by other components. In this class library I'm using unity for dependency injection. For this class library I create a test project. The caller also gets a test project. One thing I'm uncertain about is the location of the bindings. Should I incorporate this in the class library or should I do this from the calling application?
我正在使用一个可以被其他组件重用的类库。在这个类库中,我使用 unity 进行依赖注入。对于这个类库,我创建了一个测试项目。调用者还会得到一个测试项目。我不确定的一件事是绑定的位置。我应该将其合并到类库中还是应该从调用应用程序中执行此操作?
采纳答案by Aliostad
This is an interesting problem. How can you dependency inject re-usable assemblies that do not have an entry point. I would really like to see other people's answer.
这是一个有趣的问题。您如何依赖注入没有入口点的可重用程序集。我真的很想看看其他人的答案。
Dependency injection is the responsibility of the entry-point assembly. Yet, if you have a lot of classes and assemblies each needing DI, then it is possible that they are left-off for some classes/assemblies and the task becomes onerous.
依赖注入是入口点程序集的责任。然而,如果您有很多类和程序集都需要 DI,那么它们可能会被某些类/程序集遗漏,并且任务变得繁重。
Solution One
解决方案一
Using convention over configuration. You stick to a rule of class Fooimplementing IFoo, etc. A lot of DI frameworks have the means to set it up using convention.
使用约定优于配置。你坚持类Foo实现的规则IFoo,等等。很多 DI 框架都有使用约定来设置它的方法。
Solution two
解决方案二
Above solution does not solve all problems since sometimes you need to parameterise the setup of the injection. Here is how I have solved the problem (especially for those assemblies loaded by MEFand this is for AutoFac):
上述解决方案并不能解决所有问题,因为有时您需要参数化注射设置。这是我解决问题的方法(特别是对于MEF加载的那些程序集,这是为AutoFac):
Created an interface IIocInstallerwhere container (or builder is passed)
创建了一个IIocInstaller传递容器(或构建器)的接口
public interface IIocInstaller
{
void Setup(ContainerBuilder builder);
}
Created an assembly attribute that flags assemblies needing DI:
创建了一个程序集属性来标记需要 DI 的程序集:
[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}
In each assembly, I create a class that sets up DI:
在每个程序集中,我创建一个设置 DI 的类:
[assembly: ExportAssembly]
namespace This.That
{
[Export(typeof(IIocInstaller))]
public class IocInstaller : IIocInstaller
{
public void Setup(ContainerBuilder builder)
{
....
}
}
}
Then in the entry point, I have a common code which looks through all loaded assemblies (including MEFed ones) that have the assembly attribute and then look for the type implementing the IIocInstallerand then call Setup on them.
然后在入口点,我有一个通用代码,它查看所有加载的具有程序集属性的程序集(包括 MEFed 程序集),然后查找实现 的类型IIocInstaller,然后对它们调用 Setup。
回答by Ventsyslav Raikov
Doing it from the calling application puts more burden on the calling application. Leaving the chance to omit the initialization and get into trouble.
从调用应用程序执行此操作会给调用应用程序带来更多负担。留下机会省略初始化并陷入困境。
I would do it in the class library, for example in a static constructor.
我会在类库中这样做,例如在静态构造函数中。
回答by Rodney S. Foley
I know that an answer has been chosen, however I think a part of Unity is being overlooked. Since this was a specific Unity question I thought I point out the UnityContainerExtension base class that implements the IUnityContainerExtensionConfigurator. This is there for API library to extend to make it easy for the entry-point application who owns the Container to have an easy way to make sure your library gets registered with the Container correctly, and allows the API owner control of what gets registered and how.
我知道已经选择了一个答案,但是我认为 Unity 的一部分被忽略了。由于这是一个特定的 Unity 问题,我想我指出了实现 IUnityContainerExtensionConfigurator 的 UnityContainerExtension 基类。这是用于 API 库进行扩展的地方,以便拥有容器的入口点应用程序可以轻松地确保您的库正确注册到容器中,并允许 API 所有者控制注册的内容和如何。
This is used by the Microsoft Enterprise Libraries for this purpose.
为此,Microsoft 企业库使用它。
I am going to use a Logging library as a simple:
我将使用一个 Logging 库作为一个简单的:
public class LoggingUnityExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
}
}
Then the entry-point application does this:
然后入口点应用程序执行以下操作:
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.AddNewExtension<EnterpriseLibraryCoreExtension>();
Container.AddNewExtension<LoggingUnityExtension>();
// ...
}
// ...
}
Now they have registered Enterprise Library and the API for the Logging library. It's very simple for the entry-point application with this method which is what any library developer should have as a goal.
现在他们已经注册了企业库和日志库的 API。使用这种方法的入口点应用程序非常简单,这是任何库开发人员都应该拥有的目标。
回答by Ta?yürek G?k?ah
O.K Create a library named Project.Ioc. Install Unity here. Reference the other layers to Ioc library. And Ioc Library to presentation layer. Create a class named UnityHelper.
OK 创建一个名为 Project.Ioc 的库。在此处安装 Unity。将其他层引用到 Ioc 库。和 Ioc 库到表示层。创建一个名为 UnityHelper 的类。
/// <summary>
/// Bind the given interface in request scope
/// </summary>
public static class IocExtensions
{
public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
}
public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
}
}
/// <summary>
/// The injection for Unity
/// </summary>
public static class UnityHelper
{
public static IUnityContainer Start()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container));
return container;
}
/// <summary>
/// Inject
/// </summary>
/// <returns></returns>
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// Database context, one per request, ensure it is disposed
container.BindInRequestScope<IMVCForumContext, MVCForumContext>();
container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
//Bind the various domain model services and repositories that e.g. our controllers require
container.BindInRequestScope<ITopicService, TopicService>();
container.BindInRequestScope<ITopicTagRepository, TopicTagRepository>();
//container.BindInRequestScope<ISessionHelper, SessionHelper>();
return container;
}
}
Check out the MvcForum project. There is MvcForm.Ioc class library. The library gets other Layer references. There are only one class named UnityHelper.
查看 MvcForum 项目。有 MvcForm.Ioc 类库。该库获取其他层引用。只有一个名为 UnityHelper 的类。
https://github.com/leen3o/mvcforum
https://github.com/leen3o/mvcforum
i hope this is wat you are looking for.
我希望这是你正在寻找的。

