【问题标题】:using modules and config files in autofac在 autofac 中使用模块和配置文件
【发布时间】:2011-04-25 17:07:21
【问题描述】:

虽然我通常发现 Autofac 文档(在 wiki 上)很有帮助,但关于 XML 配置和模块的部分对我来说有点不清楚。现在,我有一个示例工作(我将在下面介绍),但我不确定它是否代表 Autofac 上下文中的一种混蛋配置方法。特别是,我不确定配置文件和代码文件中是否有我真正需要的内容。

代码如下:

using System;
using System.IO;
using Autofac;
using Autofac.Configuration;

namespace AutofacTest.Animals
{
    interface IAnimal
    {
        void Speak ( );
    }

    abstract class Animal : IAnimal
    {
        protected TextWriter Writer
        {
            get;
            private set;
        }

        protected Animal ( TextWriter writer )
        {
            this.Writer = writer;
        }

        public abstract void Speak ( );

    }

    class Dog : Animal
    {

        public Dog ( TextWriter writer )
            : base ( writer )
        {

        }

        public override void Speak ( )
        {
            this.Writer.WriteLine ( "Arf!" );
        }
    }

    class Cat : Animal
    {
        public Cat ( TextWriter writer )
            : base ( writer )
        {

        }

        public override void Speak ( )
        {
            this.Writer.WriteLine ( "Meow" );
        }
    }

    // In actual practice, this would be in a separate assembly, right?
    class AnimalModule : Module
    {
        protected override void Load ( ContainerBuilder builder )
        {
            builder.RegisterInstance ( Console.Out ).As<TextWriter> ( ).SingleInstance ( );
            builder.Register ( d => new Dog ( d.Resolve<TextWriter> ( ) ) ).As<IAnimal> ( );
        }
    }

    class Program
    {
        static void Main ( )
        {
            Console.ForegroundColor = ConsoleColor.Yellow;

            ContainerBuilder builder = new ContainerBuilder ( );
            ConfigurationSettingsReader reader = new ConfigurationSettingsReader(); 
            builder.RegisterModule ( reader );
            //builder.RegisterModule ( new AnimalModule ( ) );
            builder.Build ( ).Resolve<IAnimal> ( ).Speak ( );
            Console.ReadKey ( );
        }
    }
}

这是一个相关的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
    </configSections>
    <autofac defaultAssembly="AutofacTest">
        <components>
            <component
                type="AutofacTest.Animals.Cat"
                service="AutofacTest.Animals.IAnimal" />
            <component type="System.IO.StreamWriter" service="System.IO.TextWriter">
                <parameters>
                    <parameter name="path" value="C:\AutofacTest.txt"/>
                    <parameter name="append" value="false" />
                </parameters>
                <properties>
                    <property name="AutoFlush" value="true" />
                </properties>
            </component>
        </components>
        <modules>
            <module type="AutofacTest.Animals.AnimalModule, AutofacTest"/>
        </modules>
    </autofac>
</configuration>

这一切都很好。应用程序将“喵”输出到文本文件。如果我注释掉组件元素,应用程序会输出“Arf!”到控制台。

那么,这里一切都好吗?或者有没有更好的方法来解决这个问题?

而且我有点不确定基于模块的配置背后的想法:

我是否正确,在实际实践中,模块应该与应用程序的其余部分位于不同的程序集中?

我是否正确理解模块的主要功能之一是为 DI 容器提供一组默认配置设置?

理想情况下,我的配置文件应该有多大?换句话说,在使用 Autofac 时,我需要注意哪些配置文件反模式?

提前感谢(我认为)您的回复。

音乐家

【问题讨论】:

  • 只是一个提醒,可以节省其他人的时间和精力 - 在 AutoFac 4.0 中,这不再有效。有关如何使用配置,请参阅 4.0 版的文档。

标签: autofac


【解决方案1】:

我个人的建议是谨慎使用 XML 配置。我只会将它用于您知道无需重新编译即可重新配置的部分。例如,如果您正在构建一个可重用的库,那么这可能比构建一个单一的 web 应用程序要多。我尝试做的另一件事是使用以下代码使我的大多数类型自动注册:

public static void AutoRegister(ContainerBuilder builder, params Assembly[] assemblies)
{
    builder.RegisterAssemblyTypes(assemblies)
        .Where(t => t.GetCustomAttributes(typeof (RegisterServiceAttribute), false).Any())
        .AsSelf()
        .AsImplementedInterfaces();
}

RegisterServiceAttribute 是我根项目中的一个属性:

[AttributeUsage(AttributeTargets.Class)]
[MeansImplicitUse]
public class RegisterServiceAttribute : Attribute
{
}

注意:MeansImplicitUse 来自 Resharper。

然后我将[RegisterService] 放在我想自动注册的任何课程上。我的注册中至少有 95% 是这样处理的。其余的注册发生在调用 AutoRegister() 之后。

【讨论】:

  • 感谢吉姆,您的回复。我需要考虑一下您的建议如何与我们正在尝试做的事情相吻合。
  • 是否可以在一个应用程序的 xml 和代码中注册一些服务?
【解决方案2】:

从您的示例中,我不能 100% 确定预期的行为是什么 - 似乎您多次注册同一组组件,如果这是您的意图,请忽略这些建议。

  • 如果您在 XML 中注册一个模块,您也不需要在该模块中注册组件。
  • 同样,如果您在 XML 中注册模块,则无需在代码中也注册该模块。

关于“最佳实践”,我认为 Jim 建议谨慎使用 XML 是一个很好的建议。就个人而言,我倾向于在模块内部完成所有繁重的工作,然后通过 XML 注册模块以利用可以在其中应用的配置。

我提出的另一个建议是仅使用 XML 来配置模块。在您的示例中,您正在对组件进行配置;如果您将参数应用于模块,然后在该模块内部根据需要将它们传递给组件,则配置不会那么脆弱。模块不会经常变动,而组件需要能够在不破坏配置的情况下进行更改。

HTH,

尼克

【讨论】:

    猜你喜欢
    • 2020-09-06
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多