我个人喜欢从C#代码配置StructureMap的选项。根据我的理解,DI的优点之一是我们可以轻松交换新的具体实例。但是,如果配置是在代码中定义的,那么具体实例在dll中是硬编码的。
所以,实际上,它与硬件编码依赖关系一样好,对吧?我知道,在测试期间它会让生活更轻松......
我的观点是,使用xml配置不是更好吗?你想插入一个新的具体实例?只需让安装程序用新的文件覆盖structuremap.config文件。
那么,配置StructureMap的首选方法是什么?
额外:我暂时被迫使用C#配置,因为我不知道如何将连接字符串传递给实例。我可以在配置文件中编写连接字符串,但我想重用app.config中定义的连接字符串。
答案 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>