10

I personally like the option to configure StructureMap from C# code. From what I understand, one of the advantages of DI, is that we can easily swap in a new concrete instance. But, if the configuration is defined in code, then the concrete instances are hardcoded in the dll.

So, practically, its as good as having hard coded the dependencies, right? I know, during testing it makes life easier...

My point is, wouldnt it be better to use xml configuration instead? you want to plugin a new concrete instance? simply have your installer overwrite the structuremap.config file with the new one.

So, what is the preferred way to configure StructureMap?

Extra: Am forced to use C# configuration for the time being because I dont know how to pass the connection string to instance. I can write the connectionstring in the config file, but i would like to reuse the connectionstring defined in app.config.

alexandrul
  • 12,856
  • 13
  • 72
  • 99
Amith George
  • 5,806
  • 2
  • 35
  • 53

2 Answers2

17

No matter which particular DI Container you use, you should always defer the resolution of the application's object graph to the last responsible moment. This is called the application's Composition Root.

You can write the bulk of your application without ever referencing the DI Container. This also means that you can defer the decision between configuration in code or config until you need it.

You shouldn't need the container at all for unit testing, but may need it for integration testing. However, in integration tests, you will likely need a different configuration for the container than in the final application.

All in all, configuring the container in code is the preferred approach these days because it's more robust and you can apply convention-based configuration mechanics.

XML configuration tends to be more brittle and too verbose. In most cases, it simply slows you down because you get no refactoring or compiler support.

However, XML configuration is still valid when you need to be able to swap dependencies without recompiling the application. Most DI Containers will let you mix those approaches so that you can have most of your configuration in code, but a few selected dependencies defined in XML for extensibility reasons.

Community
  • 1
  • 1
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • While I agree with your answer. It seems the question really asked how do I get my application configuration into my types. – KevM Feb 17 '10 at 14:14
  • @KevM, not really. My question was more about which configuration option is better. It arose, because I was having difficulty getting my connection string in to my types using xml. I would have to have written the connection string one more time in the structuremap.config file. I had wanted to avoid having to maintain the connectionstring at two places. – Amith George Feb 19 '10 at 18:36
  • You are wise to avoid duplication. This is exactly what the "equal to app setting" capabilities of StructureMap are for in basic configuration mapping scenarios. – KevM Feb 19 '10 at 19:16
  • From my experience it is not possible to use c#. because sometimes you cannot refer a dll because of circular reference . In such cases only xml configuration works. – Blue Clouds Jun 07 '15 at 18:31
  • 1
    @BlueClouds If you have a circular reference, then you have a *problem*. XML configuration may give you symptomatic relief, but doesn't address your underlying problem. – Mark Seemann Jun 07 '15 at 18:47
  • @MarkSeemann even when there is no circular reference issues, an assembly might be forced to reference other assemblies just to reference it in the container. This unnecessary reference can be avoided by referencing in xml. And on the circular reference , I don't think solving circular reference with xml is a 'problem'. The problem we are addressing is separation of concerns. And the legal limit is 'no compilation error'. But I don't have the design with me to prove it. I did it some time ago. Next time I am at it I will bring it here. So we can discuss. – Blue Clouds Jun 10 '15 at 11:43
  • @BlueClouds May I recommend that you (re)read the chapters on Package Management Principles in [APPP](http://amzn.to/19W4JHk)? Here, Robert C. Martin explains in detail the reasons why circular package references should be avoided. – Mark Seemann Jun 10 '15 at 13:30
  • @BlueClouds You may also want to read this on composition from the root of the application: http://stackoverflow.com/a/9503612/126014 – Mark Seemann Jun 10 '15 at 13:35
6

To answer your question you can have your cake and eat it too in StructureMap. You can configure your container from code and push in that extra bit of config you need from the application configuration. That is what EqualToAppSetting is for.

Create a settings class

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

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

Next tell StructureMap to configure it using your application settings.

        [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;");
    }

Finally here is what the application settings look like in my application config:

    <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>
KevM
  • 2,496
  • 1
  • 22
  • 25
  • I did think about this, but the downside to me was that I would have to track the connectionstring at two places. one here and once in the connectionstring section of the web/app.config... Thanks for the reply :) – Amith George Feb 19 '10 at 17:24
  • am using your suggestion at the moment to solve my connection string issue. At the application start I edit the web.config to include a new app setting called connectionString. It gets its value from the connectionString defined in the proper connectionStrings section. Thus I have to modify the connection string only at one place. and my structuremap config can read it from the appsettings... thanks! – Amith George Feb 19 '10 at 18:39
  • Happy to help. We baked a way to conventionally pull config into settings objects to avoid any container configuration. I should really blog about that. – KevM Feb 19 '10 at 19:13