我正在使用一个可以被其他组件重用的类库。在这个类库中,我使用统一进行依赖注入。对于这个类库,我创建了一个测试项目。调用者还会得到一个测试项目。我不确定的一件事是绑定的位置。我应该将其合并到类库中还是应该从调用应用程序中执行此操作?
4 回答
我知道已经选择了一个答案,但是我认为 Unity 的一部分被忽略了。由于这是一个特定的 Unity 问题,我想我指出了实现 IUnityContainerExtensionConfigurator 的 UnityContainerExtension 基类。这是为了扩展 API 库,以便拥有 Container 的入口点应用程序可以轻松地确保您的库正确注册到 Container 中,并允许 API 所有者控制注册的内容和如何。
Microsoft 企业库为此目的使用它。
我将简单地使用 Logging 库:
public class LoggingUnityExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
}
}
然后入口点应用程序执行此操作:
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.AddNewExtension<EnterpriseLibraryCoreExtension>();
Container.AddNewExtension<LoggingUnityExtension>();
// ...
}
// ...
}
现在他们已经注册了 Enterprise Library 和 Logging 库的 API。使用这种方法的入口点应用程序非常简单,这是任何库开发人员都应该拥有的目标。
这是一个有趣的问题。您如何依赖注入没有入口点的可重用程序集。我真的很想看看其他人的答案。
依赖注入是入口点程序集的职责。但是,如果您有很多类和程序集,每个都需要 DI,那么它们可能会被某些类/程序集遗漏,并且任务变得繁重。
解决方案一
使用约定优于配置。你坚持类Foo
实现IFoo
等规则。许多 DI 框架都有使用约定来设置它的方法。
解决方案二
上述解决方案并不能解决所有问题,因为有时您需要参数化注射设置。这是我解决问题的方法(特别是对于那些由MEF加载的程序集,这是针对AutoFac
):
创建了一个接口IIocInstaller
,其中传递了容器(或构建器)
public interface IIocInstaller
{
void Setup(ContainerBuilder builder);
}
创建了一个程序集属性,用于标记需要 DI 的程序集:
[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}
在每个程序集中,我创建一个设置 DI 的类:
[assembly: ExportAssembly]
namespace This.That
{
[Export(typeof(IIocInstaller))]
public class IocInstaller : IIocInstaller
{
public void Setup(ContainerBuilder builder)
{
....
}
}
}
然后在入口点,我有一个通用代码,它查看所有加载的具有程序集属性的程序集(包括 MEFed 程序集),然后查找实现的类型IIocInstaller
,然后在它们上调用 Setup。
从调用应用程序执行此操作会给调用应用程序带来更多负担。留下机会忽略初始化并陷入困境。
我会在类库中进行,例如在静态构造函数中。
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;
}
}
查看 MvcForum 项目。有 MvcForm.Ioc 类库。该库获取其他图层引用。只有一个名为 UnityHelper 的类。
https://github.com/leen3o/mvcforum
我希望这是你要找的。