Xml配置还是通过代码配置?

时间:2010-02-17 11:22:25

标签: dependency-injection inversion-of-control structuremap

我个人喜欢从C#代码配置StructureMap的选项。根据我的理解,DI的优点之一是我们可以轻松交换新的具体实例。但是,如果配置是在代码中定义的,那么具体实例在dll中是硬编码的。

所以,实际上,它与硬件编码依赖关系一样好,对吧?我知道,在测试期间它会让生活更轻松......

我的观点是,使用xml配置不是更好吗?你想插入一个新的具体实例?只需让安装程序用新的文件覆盖structuremap.config文件。

那么,配置StructureMap的首选方法是什么?

额外:我暂时被迫使用C#配置,因为我不知道如何将连接字符串传递给实例。我可以在配置文件中编写连接字符串,但我想重用app.config中定义的连接字符串。

2 个答案:

答案 0 :(得分:17)

无论您使用哪个特定DI容器,都应始终将应用程序对象图的分辨率推迟到last responsible moment。这称为应用程序的Composition Root

您可以编写大部分应用without ever referencing the DI Container。这也意味着您可以在代码或配置之间推迟配置,直到您需要它为止。

shouldn't need the container at all for unit testing,但可能需要它进行集成测试。但是,在集成测试中,您可能需要与最终应用程序不同的容器配置。

总而言之,如今,在代码中配置容器是首选方法,因为它更强大,您可以应用基于约定的配置机制。

XML配置往往更脆弱,更冗长。在大多数情况下,它只会减慢您的速度,因为您没有重构或编译器支持。

但是,当您需要能够交换依赖项而不重新编译应用程序时,XML配置仍然有效。大多数DI容器都允许您混合这些方法,以便您可以在代码中使用大部分配置,但出于可扩展性原因,在XML中定义了一些选定的依赖项。

答案 1 :(得分:6)

要回答你的问题,你可以在StructureMap中吃蛋糕并吃掉它。您可以从代码配置容器,并从应用程序配置中推送您需要的额外配置。这就是EqualToAppSetting的用途。

创建设置类

    public class DatabaseSettings
{
    public DatabaseSettings(string type, string connectionString)
    {
        Type = type;
        ConnectionString = connectionString;
    }

    public string Type { get; set; }
    public string ConnectionString { get; set; }
}

接下来告诉StructureMap使用您的应用程序设置对其进行配置。

        [Test]
    public void setup_concrete_class_via_application_configuration()
    {
        var container = new Container(config =>
        {
            config.ForConcreteType<DatabaseSettings>().Configure
                .Ctor<string>("type").EqualToAppSetting("dovetail.database.type", "mssql")
                .Ctor<string>("connectionString").EqualToAppSetting("dovetail.database.connectionString");

        });

        var databaseSettings = container.GetInstance<DatabaseSettings>();
        databaseSettings.Type.ShouldEqual("mssql");
        databaseSettings.ConnectionString.ShouldEqual("Data Source=.; Initial Catalog=dovetail;User Id=sa;Password=sa;");
    }

最后,这是我的应用程序配置中的应用程序设置:

    <appSettings>
    <add key="dovetail.database.type" value="mssql"/>
    <add key="dovetail.database.connectionString" value="Data Source=.;Initial Catalog=dovetail;User Id=sa;Password=sa;"/>    
</appSettings>