Combining Unity container setup through code + configuration

May 11, 2011 at 11:34 PM

I have a unity container that I have setup through code, but have application blocks' setup information in separate config files. I see a solution that will allow keeping entlib configurations in separate files, but require that all configuration happen through configuration files only. What I am looking for is to setup unity container through code and when I do container.AddNewExtension<EnterpriseLibraryCoreExtensions>(), it should go through app.config and load the configurations for any application blocks mentioned or referenced there. The way I have set it up, I have an app.config that points to a logging.config for Logging Application Block settings but I am getting an error during container setup. I am still investigating the root cause of the problem and will post specific exceptions / error messages as I discover them, but just wanted to get a quick confirmation if what I am attempting is even legal.

For your reference, here is my app.config (only relevant portions produced below. I have verified there is no error in any other parts of app.config; if I comment out this part, it works fine):

<!--Enterprise Library Settings-->
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  <loggingConfiguration configSource="logging.config"/>

Here is my logging.config (some may argue that if you are coming here through configSource, you should not put enclosing <configuration> tags, but removing them does not fix the problem either. The logging configurations were generated through Enterprise Library Configuration Editor, so I don't anticipate any syntactical issues either):

  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
            <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                source="Enterprise Library Logging" formatter="Text Formatter"
                log="" machineName="." traceOutputOptions="None" />
            <add name="WMI Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.WmiTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.WmiTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
                name="Text Formatter" />
            <add switchValue="All" name="General">
                    <add name="WMI Trace Listener" />
            <allEvents switchValue="All" name="All Events" />
            <notProcessed switchValue="All" name="Unprocessed Category" />
            <errors switchValue="All" name="Logging Errors &amp; Warnings">
                    <add name="Event Log Listener" />

May 12, 2011 at 12:34 AM

Quick update: the settings shown above seem to work in a console program, but fail in Windows service. I would still look for official confirmation so I don't get some surprises down the road. Attempting to debug Windows Service errors now.

May 12, 2011 at 11:19 AM

I'm not sure if I understand your porblem

in WindowsService the Working CurrentDirectory is System32. probably does not load your configuration.

Try set the CurrentDirectory before start your service:


May 12, 2011 at 6:38 PM

Thank you for your response. Path is most certainly not the problem here because:

1. I know app.config is being read correctly because it has some connectionstrings and WCF settings that drive Entities and Web Services setup both of which are working correctly.

2. I have the problem even if I took all of logging.config and stuck it in app.config. I copy over logging.config to the bin directory which is where exe.config for the Windows Service gets written. So if it can read

app.config, it should be able to find logging.config. I even tried turning requiredPermission to false thinking that there could be a trust issue since Windows Service runs under a low level id.

3. I did give your solution a shot, and it did not fix the problem.


So, to answer your question about what is exactly is the problem we are trying to solve:

I think the key problem is making logging settings work through configuration files (never mind separating out logging settings into a separate configSource). So far, I have not had this problem because I was doing all container setups through code rather than config files. I suspect

that if I attempt to setup the unity container through config files I am going to run into a similar problem. Obviously, I am missing some basic step.

Here is the code I have in my windows service Main(). This is probably more information than you need; if I took out loggingConfiguration from the equation, everything works just fine. So there is probably some

problem when executing .AddNewExtension<EnterpriseLibraryCoreExtension>():

       private static void Main()
            using(IUnityContainer container=new UnityContainer())
                        new ContainerControlledLifetimeManager(),
                        new Interceptor(typeof(VirtualMethodInterceptor),"VMInterceptor"),
                        new InterceptionBehavior<PolicyInjectionBehavior>()
                    .AddMatchingRule(typeof(TagAttributeMatchingRule), new InjectionConstructor("MyMethod"))
                        new ContainerControlledLifetimeManager(),
                        new InjectionConstructor
                container.RegisterType<IMyWebService, MyWebService>();
                container.RegisterType<IRepository, Repository>("entity",new ContainerControlledLifetimeManager());
                    Assembly.LoadFrom(String.Format("{0}\\My.Resources.dll", System.AppDomain.CurrentDomain.BaseDirectory)),
                    new ContainerControlledLifetimeManager());
                EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);

May 16, 2011 at 8:53 PM

I couldn't figure this out; probably some setups are incorrect in my environment. For the time being I have taken the Fleunt API route to setup logging application block; seems to be working correctly for now. I will try to come back to this problem once my immediate priorities are covered.