Question

When developing my site using ASP.NET MVC (C#) I've used Domain Driven Design (N-Tier) as the architecture.

I'm wondering how can I create a settings/configurations for my app (without using database table).

I thought firstly about .settings file, but I still don't sure that this is the right approach to take (where should it live, for instance?). So then I've added the config values in web.config and then created in the core layer a t4 template which generates AppConfigurationManager from the web.config in order to not break DDD design.

Still I think that I'm using a bad approach.

So, how do you recommend to save a configurations when dealing with Domain Driven Design?

My t4 template (in case it can help to get the idea):

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly Name="System.Configuration" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Linq" #>
<#@ assembly name="System.Collections" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ assembly name="System.Net" #>
<#@ assembly name="System" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Net" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//  
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
using System;
using System.Configuration;

namespace KNadlan.Core.Configuration
{
    public partial class AppConfigurationManager
    {
        <#
        string path = @"C:\Visual Studio 2012\Projects\MyApp\MyApp.Web.UI\Web.config";
        string configNamespace = "myapp";

        var xDocument = XDocument.Load(path);
        var results =   xDocument.Descendants("appSettings");

        foreach (var xElement in results.Descendants())
        {
            string origKeyName = xElement.Attribute("key").Value.Trim();
            string keyName = origKeyName;

            /* Skip on third-party configurations */
            if (!string.IsNullOrEmpty(configNamespace))
            {
                if (!keyName.StartsWith(string.Format("{0}:", configNamespace)))
                {
                    continue;
                }

                keyName = keyName.Substring(string.Format("{0}:", configNamespace).Length);
            }

            /* Valid key? */
            if (!System.Text.RegularExpressions.Regex.IsMatch(keyName, @"^([a-zA-Z0-9]+)$", System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.IgnoreCase))
            {
                continue;
            }

            /* Format field and property names */
            string fieldName = "_" + keyName.Substring(0, 1).ToLower() + keyName.Substring(1);
            string propertyName = keyName.Substring(0, 1).ToUpper() + keyName.Substring(1);
            #>

        #region <#= propertyName #>

        private static string <#= fieldName #> = ConfigurationManager.AppSettings["<#= origKeyName #>"];
        public static string <#= propertyName #>
        {
            get { return <#= fieldName #>; }
            set
            {
                <#= fieldName #> = value;
                ConfigurationManager.AppSettings["<#= origKeyName #>"] = value;
            }
        }

        #endregion
        <#
        }
        #>
    }
}
Was it helpful?

Solution

Accessing to the configuration from the domain layer is sometimes suitable for domain services, but it can make the service a bit harder to test in isolation.

You should avoid such access from entities and value objects, btw.

A better path is reading the configuration in the infrastructure layer and injecting the required values via constructor's arguments in the domain objects. Note that factories and repository are part of the infrastructure, thus they can access such configurations if required.

Finally a important note, out of experience: keep configuration as small as possible. In .NET the .config file is the best place for configuration since it's where developers are already trained to look there. But in enterprise applications, they are likely to grow uncontrolled since each developer want to code flexible components. This is a smell of poor architecture: only make configurable what you know that will be used with different configurations.

It's easier to add a configuration section later, when actually needed, than remove a section that is cut&pasted at each deploy. Such configurations are likely to be overdesigned for a flexibility that they don't need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top