Конфигурация XML или Конфигурация через код? - PullRequest
10 голосов
/ 17 февраля 2010

Мне лично нравится опция настройки StructureMap из кода C #. Из того, что я понимаю, одно из преимуществ DI заключается в том, что мы можем легко заменить новый конкретный экземпляр. Но, если конфигурация определена в коде, то конкретные экземпляры жестко закодированы в dll.

Итак, практически так же хорошо, как жестко закодировать зависимости, верно? Я знаю, во время тестирования это облегчает жизнь ...

Суть в том, не лучше ли вместо этого использовать конфигурацию xml? Вы хотите подключить новый конкретный экземпляр? просто попросите ваш установщик перезаписать файл structuremap.config новым.

Итак, каков предпочтительный способ настройки StructureMap?

Дополнительно: на данный момент я вынужден использовать конфигурацию C #, потому что я не знаю, как передать строку подключения в экземпляр. Я могу написать строку подключения в файле конфигурации, но я хотел бы повторно использовать строку подключения, определенную в app.config.

Ответы [ 2 ]

17 голосов
/ 17 февраля 2010

Независимо от того, какой конкретный DI-контейнер вы используете, вы всегда должны откладывать разрешение графа объектов приложения до последнего ответственного момента . Это называется корень композиции приложения .

Вы можете написать основную часть вашего приложения , даже не ссылаясь на DI-контейнер . Это также означает, что вы можете отложить выбор между конфигурацией в коде или в конфигурации, пока она вам не понадобится.

Вам вообще не нужен контейнер для модульного тестирования , но он может понадобиться для интеграционного тестирования. Однако в интеграционных тестах вам, вероятно, потребуется другая конфигурация для контейнера, чем в конечном приложении.

В целом, настройка контейнера в коде является предпочтительным подходом в наши дни, потому что он более устойчив, и вы можете применять основанную на соглашениях механику конфигурации.

Конфигурация XML имеет тенденцию быть более хрупкой и слишком многословной. В большинстве случаев это просто замедляет работу, потому что вы не получаете рефакторинга или поддержки компилятора.

Тем не менее, конфигурация XML остается в силе, когда вам нужно поменять местами зависимости без перекомпиляции приложения. Большинство DI-контейнеров позволяют вам смешивать эти подходы, так что вы можете иметь большую часть своей конфигурации в коде, но несколько выбранных зависимостей, определенных в XML для целей расширяемости.

6 голосов
/ 17 февраля 2010

Чтобы ответить на ваш вопрос, вы можете съесть свой торт и съесть его в 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>
...