31

我正在使用一个可以被其他组件重用的类库。在这个类库中,我使用统一进行依赖注入。对于这个类库,我创建了一个测试项目。调用者还会得到一个测试项目。我不确定的一件事是绑定的位置。我应该将其合并到类库中还是应该从调用应用程序中执行此操作?

4

4 回答 4

27

我知道已经选择了一个答案,但是我认为 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。使用这种方法的入口点应用程序非常简单,这是任何库开发人员都应该拥有的目标。

于 2012-09-04T16:49:56.160 回答
8

这是一个有趣的问题。您如何依赖注入没有入口点的可重用程序集。我真的很想看看其他人的答案。

依赖注入是入口点程序集的职责。但是,如果您有很多类和程序集,每个都需要 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。

于 2012-04-17T12:29:02.390 回答
2

从调用应用程序执行此操作会给调用应用程序带来更多负担。留下机会忽略初始化并陷入困境。

我会在类库中进行,例如在静态构造函数中。

于 2012-04-17T12:24:58.350 回答
0

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

我希望这是你要找的。

于 2015-09-17T11:46:16.983 回答