Tripping over logs: A story of Unity - Part 5
Recap + Intro
In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Then in part 3 we saw some benefits of dealing with this overhead. Previously we actually got our logging nicely sorted but there was a few extra details worth mentioning, so here goes.
Note you can get Unity with the Enterprise Library from p&p group.
As I said in part 1
what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
Circular References
DI is actually a minefield since you can cause a circular reference easily, but injection makes that even easier to shoot yourself in the foot. What is a circular reference? The documentation (shockingly) describes it well:
- Objects generated through constructor injection that reference each other in their constructor parameters
- Objects generated through constructor injection where an instance of a class is passed as a parameter to its own constructor
- Objects generated through method call injection that reference each other
- Objects generated through property (setter) injection that reference each other
For example, the following code shows two classes that reference each other in their constructors.
public class Class1{public Class1(Class2 test2)
{ ... }}public class Class2{public Class2(Class1 test1)
{ ... }}It is the responsibility of the developer to prevent this type of error by ensuring that the members of classes they use with dependency injection do not contain circular references.
I have bolded that last line to get the point across. You have been warned!
Reflection
It’s not just interception that uses reflection, other parts do as well so make sure you understand the security implications of this: http://msdn.microsoft.com/en-us/library/9syytdak.aspx
Interceptors
I used the transparent proxy interceptor in my previous post, but there are two others. Each has pro’s and con’s, which the documentation puts in a simple table for you:
Type
Description
Use
TransparentProxyInterceptor
An instance interceptor. The proxy is created by using the .NET TransparentProxy/RealProxy infrastructure.
When the type to intercept is a MarshalByRefObject or when only methods from the type's implemented interfaces need to be intercepted.
InterfaceInterceptor
An instance interceptor. It can proxy only one interface on the object. It uses dynamic code generation to create the proxy class.
When resolving an interface mapped to a type.
VirtualMethodInterceptor
A type interceptor. It uses dynamic code generation to create a derived class that gets instantiated instead of the original, intercepted class and to hook up the call handlers.
When only virtual methods need to be intercepted.
Selection of a specific interceptor depends on your specific needs, because each one has various tradeoffs. The following table summarizes the three interceptors and their advantages and disadvantages.
Type
Advantages
Disadvantages
TransparentProxyInterceptor
Can intercept all methods of the target object (virtual, non-virtual, or interface).
The object must either implement an interface or inherit from System.MarshalByRefObject. If the marshal by reference object is not a base class, you can only proxy interface methods. The TransparentProxy process is much slower than a regular method call.
InterfaceInterceptor
Proxy supports casting to all the interfaces or types of the target object.
It only intercepts methods on a single interface. It cannot cast a proxy back to target object's class or to other interfaces on the target object.
VirtualMethodInterceptor
Calls are much faster than the TransparentProxyInterceptor.
Interception only happens on virtual methods. You must set up interception at object creation time and cannot intercept an existing object.
Rules
There is an entire rules framework available in interception which lets you enable/disable the interception based on rules. The idea is that you annotate all methods and then use the rules to filter which of those to actually run. This can, as with everything in Unity, be configured in code or in the configuration file. Here are a list of the rules (I am sure you can begin to guess what they do by their names):
- The Assembly Matching Rule
- The Custom Attribute Matching Rule
- The Member Name Matching Rule
- The Method Signature Matching Rule
- The Namespace Matching Rule
- The Parameter Type Matching Rule
- The Property Matching Rule
- The Return Type Matching Rule
- The Tag Attribute Matching Rule
- The Type Matching Rule
And as always you can custom develop your own rules too.
Tripping over logs: A story of Unity - Part 4
Recap + Intro
In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Then in part 3 we saw some benefits of dealing with this overhead, but now dear reader we get into the real issue I wanted to solve, having logging be more elegantly applied.
Note you can get Unity with the Enterprise Library from p&p group.
As I said in part 1
what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
Works better than Vader’s interceptor
(Once again I shine my knowledge of Star Wars in a title… which maybe is why my friends and family think of me as a geek and I see myself as cool… anyway it’s not important to the post.)
The Mary Poppins bag like magic that is happening with Unity is NOT just limited to controlling the lifetime of objects, it is actually controlling the objects. There is an invisible layer there and this allows us to do something very smart called Interception. In this scenario we intercept calls to classes or methods and apply some other code to them! Important to note is that we can only do that to objects that Unity works with so for our example, we can’t do it to the main method or the DoSomething method directly. We can refactor DoSomething into it’s own interface and class and have Unity own it as below. The key changes from our previous code are:
- I create a instance of IWorker and do the DoSomething method of it, passing it the logger - lines 14 and 15
- I have a new interface called IWorker and a new class based on it, called Worker - Lines 43 to 55
- I have removed our Lolzcat’s constructor in the logging (it’s not important to show that anymore)
1: class Program
2: {
3: static IUnityContainer container = new UnityContainer();
4:
5: static void Main(string[] args)
6: {
7: UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
8: section.Containers.Default.Configure(container);
9:
10: ILogger logger = container.Resolve<ILogger>();
11:
12: logger.LogThis("Application started");
13:
14: IWorker worker = container.Resolve<IWorker>();
15: worker.DoSomething("Robert", logger);
16:
17: Console.ReadKey();
18: logger.LogThis("Application Completed");
19: }
20: }
21:
22: public interface ILogger
23: {
24: void LogThis(string Message);
25: }
26:
27: public class DebugLogger : ILogger
28: {
29: public void LogThis(string Message)
30: {
31: System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
32: }
33: }
34:
35: public class ConsoleLogger : ILogger
36: {
37: public void LogThis(string Message)
38: {
39: Console.WriteLine("{0}: {1}", DateTime.Now, Message);
40: }
41: }
42:
43: interface IWorker
44: {
45: void DoSomething(string Username, ILogger logger);
46: }
47:
48: public class Worker : IWorker
49: {
50: void IWorker.DoSomething(string Username, ILogger logger)
51: {
52: logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
53: Console.WriteLine("Hello {0}", Username);
54: logger.LogThis("DoSomething Completed");
55: }
56: }
So this runs nicely but we are still using this logger thing all the time and it isn’t much better than before.
Setup the Interception
So to fix this we will use interception and that means we need to add two more references to our solution:
Next we add a new using to our code:
using Microsoft.Practices.Unity.InterceptionExtension;
using System.Reflection;
Yes, that is System.Reflection there. We will use reflection to figure out values at runtime for us.
And now we will add in code to allow us to attribute our methods so that logging happens for us. For those who have no idea what I mean by attribute methods, I am talking about the Decorator Pattern, which will be familiar to those using WCF and/or LINQ at least in practice even if you didn’t know it was called that.
To do that we first need to create another new class, this time derived from HandlerAttribute and all it does is gives us the attribute to decorate the code with, lines 1 to 7 below. It returns a class of LoggingHandler (via the container) and LoggingHandler is the other new. In here we have a constructor which take an instance of ILogger (lines 13 to 16) and a Invoke method (starting on line 18). The invoke method is the brains of the operation as it is what will be run when we call our method. Note it starts with us using reflection to work out the parameters (lines 20 through 25) and then calls the logger to write the PRE method message (line 27). Next it calls getNext which gets the next handler in the stack (in our case there is none). Note you control the order of handlers via the Order parameter, line 34. After all the handlers have run their PRE methods the method actually runs, and after the getNext it starts to unwind so we can do our POST method logging, line 29.
1: public class LoggingAttribute : HandlerAttribute
2: {
3: public override ICallHandler CreateHandler(IUnityContainer container)
4: {
5: return container.Resolve<LoggingHandler>();
6: }
7: }
8:
9: public class LoggingHandler : ICallHandler
10: {
11: ILogger _logger;
12:
13: public LoggingHandler(ILogger logger)
14: {
15: _logger = logger;
16: }
17:
18: public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
19: {
20: string parameters = string.Empty;
21: for (int counter = 0; counter < input.Inputs.Count; counter++)
22: {
23: ParameterInfo parameterInfo = input.Inputs.GetParameterInfo(counter);
24: parameters += parameterInfo.Name + " = " + input.Inputs[counter].ToString() + Environment.NewLine;
25: }
26:
27: _logger.LogThis(String.Format("About to call {0} with the following parameters: {1}", input.MethodBase.Name, parameters));
28: IMethodReturn msg = getNext()(input, getNext);
29: _logger.LogThis(String.Format("Call completed to {0}", input.MethodBase.Name));
30:
31: return msg;
32: }
33:
34: public int Order { get; set; }
35: }
One point I want to make here, and I think it is super cool, is note I never specify what to pass into LoggingHandler’s constructor (it needs an ILogger parameter)! Unity is smart enough to know it has an ILogger in the container and a constructor with needs one and puts them together automatically for you ;)
Right that’s a lot of code to do this, so how does it effect our other code? We’ll now our DoSomething method just looks like this below. Note the [Logging] attribute tag on line 1 which enables the logging for this method.
1: [Logging]
2: void IWorker.DoSomething(string Username)
3: {
4: Console.WriteLine("Hello {0}", Username);
5: }
If you think that in a massive system the fact we can just annotate methods to get functionality is great, it cleans the code up and means that developer X who is working on logging can change it WITHOUT any code changes :) Rock On!
Configuration for Interception
Our code does not run at this point :( Because we need to add some details the app.config for the system to use configuration. First we add an alias for our chosen method of interception on line 14, then we extend the unity config (similar concept to how we extended the .NET config with a config section) on lines 28 to 30, and lastly we configure the extension we added. The most important part here is how we link an interceptor to a class (lines 35 and 36). This means we can enable/disable interception via configuration.
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <configSections>
4: <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
5: </configSections>
6:
7: <unity>
8: <typeAliases>
9: <typeAlias alias="Logger" type="BigSystem.ConsoleLogger, BigSystem"/>
10: <typeAlias alias="ILogger" type="BigSystem.ILogger, BigSystem"/>
11: <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
12: <typeAlias alias="Worker" type="BigSystem.Worker, BigSystem"/>
13: <typeAlias alias="IWorker" type="BigSystem.IWorker, BigSystem"/>
14: <typeAlias alias="transparentProxy" type="Microsoft.Practices.Unity.InterceptionExtension.TransparentProxyInterceptor, Microsoft.Practices.Unity.Interception" />
15: </typeAliases>
16:
17: <containers>
18: <container>
19: <types>
20: <type type="ILogger" mapTo="Logger">
21: <lifetime type="singleton" />
22: </type>
23: <type type="IWorker" mapTo="Worker">
24: <lifetime type="singleton" />
25: </type>
26: </types>
27:
28: <extensions>
29: <add type="Microsoft.Practices.Unity.InterceptionExtension.Interception, Microsoft.Practices.Unity.Interception" />
30: </extensions>
31:
32: <extensionConfig>
33: <add name="interception" type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationElement, Microsoft.Practices.Unity.Interception.Configuration">
34: <interceptors>
35: <interceptor type="transparentProxy">
36: <default type="IWorker"/>
37: </interceptor>
38: </interceptors>
39: </add>
40: </extensionConfig>
41: </container>
42: </containers>
43: </unity>
44: </configuration>
And that is it! It’s been a long post so I won’t go into any specific of the interception type etc… I’ll do a supplementary post on that next.
Tripping over logs: A story of Unity - Part 3
Recap + Intro
In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Then in part 2 we took that code and added Unity which gave us control via a config file as to what class our logging should use. Now we are going to look at a benefit of having this Mary Poppins bag of magic controlled for us.
Note you can get Unity with the Enterprise Library from p&p group.
As I said in part 1
what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
The time of your life
In our code we created a global variable for the logging and just called that, but that is not always a good idea. Logging is a poor example of this, but security is a better one. If you wanted to do a security check in some methods and not others why waste time with a global variable, why not reach into the bag each time it is needed and pull one out. The problem can come in, is that performance can drop because now you are calling the constructor each time you need the object. The reality is that this issue was solved years ago in the Singleton pattern.
So can we apply that to Unity? Yes, Unity is smart enough to give us a way to do that thanks to it’s inbuilt lifetime management! To demo this I have modified the code from part 2 as follows:
- Removed the global variable for logger and replaced it with a global variable for the container (line 3 below)
- In DoSomething I ask for a logger at the start now (line 7 below)
- I got a Lolzcat to add a constructor to my ConsoleLogger class to slow it down ;) Lines 45 to 49.
- It’s not visible in the code by a new using has been added to System.Threading so that we can use the Thread.Sleep method on line 48
1: class Program
2: {
3: static IUnityContainer container = new UnityContainer();
4:
5: static void DoSomething(string Username)
6: {
7: ILogger logger = container.Resolve<ILogger>();
8:
9: logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
10: Console.WriteLine("Hello {0}", Username);
11: logger.LogThis("DoSomething Completed");
12: }
13:
14: static void Main(string[] args)
15: {
16: UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
17: section.Containers.Default.Configure(container);
18:
19: ILogger logger = container.Resolve<ILogger>();
20:
21: logger.LogThis("Application started");
22:
23:
24: DoSomething("Robert");
25: Console.ReadKey();
26: logger.LogThis("Application Completed");
27: }
28: }
29:
30: public interface ILogger
31: {
32: void LogThis(string Message);
33: }
34:
35: public class DebugLogger : ILogger
36: {
37: public void LogThis(string Message)
38: {
39: System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
40: }
41: }
42:
43: public class ConsoleLogger : ILogger
44: {
45: public ConsoleLogger()
46: {
47: Console.WriteLine("i iz in yourz codez, slowingz its downz");
48: Thread.Sleep(5000);
49: }
50:
51: public void LogThis(string Message)
52: {
53: Console.WriteLine("{0}: {1}", DateTime.Now, Message);
54: }
55: }
What happens if my code runs slowly now and the lolzcat message is shown twice (since I create the object twice). If I assume that it’s just an example of the overhead of the constructor (which it is), and that I need to live with it at least once then implementing the singleton pattern is the solution to this. To do it actually means two lines of changes to the app.config (one line if you want to be messy). First I add a new type alias for the ContainerControlledLifetimeManager which I have called singleton (line 11 below), and then I expand my type with a lifetime tag which links back to it (line 18 below).
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <configSections>
4: <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
5: </configSections>
6:
7: <unity>
8: <typeAliases>
9: <typeAlias alias="Logger" type="BigSystem.ConsoleLogger, BigSystem"/>
10: <typeAlias alias="ILogger" type="BigSystem.ILogger, BigSystem"/>
11: <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
12: </typeAliases>
13:
14: <containers>
15: <container>
16: <types>
17: <type type="ILogger" mapTo="Logger">
18: <lifetime type="singleton" />
19: </type>
20: </types>
21: </container>
22: </containers>
23: </unity>
24: </configuration>
Now I just rerun my application and I get the code twice as fast and one lolzcat message since the container (magic bag) has now created the object once and when I ask for it a second time it provides me the already created one! This is an amazingly useful system because it’s per mapping and out of the box are three lifetime managers and you can build your own.
For the sake of ease I will now copy and paste from the documentation on those three lifetime managers:
ContainerControlledLifetimeManager. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects. Unity uses this lifetime manager by default for the RegisterInstance method if you do not specify a different lifetime manager. If you want singleton behavior for an object that Unity creates when you use the RegisterType method, you must explicitly specify this lifetime manager. The behavior is as follows:
- If you used the RegisterType method to register a type, Unity creates a new instance of the registered type during the first call to the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. Subsequent requests return the same instance.
- If you used the RegisterInstance method to register an existing object, Unity returns this instance every time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes.
ExternallyControlledLifetimeManager. This lifetime manager allows you to register type mappings and existing objects with the container so that it maintains only a weak reference to the objects it creates when you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes based on attributes or constructor parameters within that class. Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. However, the container does not hold onto a strong reference to the object after it creates it, which means that the garbage collector can dispose of the object if no other code is holding a strong reference to it.
PerThreadLifetimeManager. Unity returns, on a per-thread basis, the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects on a per-thread basis. PerThreadLifetimeManager returns different objects from the container for each thread. The behavior is as follows:
- If you used the RegisterType method to register a type, Unity creates a new instance of the registered type the first time the type is resolved in a specified thread, either to answer a call to the Resolve or ResolveAll methods for the registered type or to fulfill a dependency while resolving a different type. Subsequent resolutions on the same thread return the same instance.
- Using the RegisterInstance method to register an existing object results in the same behavior as if you just registered the lifetime container with RegisterType. Therefore, it is recommended that you do not use the RegisterInstance method to register an existing object when using the PerThreadLifetimeManager.
- PerThreadLifetimeManager returns the object desired or permits the container to create a new instance if no such object is currently stored for the current thread. A new instance is also created if called on a different thread than the one that set the value. This lifetime manager does not dispose the instances it holds.
Tripping over logs: A story of Unity - Part 2
Recap + Intro
In part 1 we looked at the problem with just adding logging code and how it quickly gets messy and we looked at how the more loosely coupled the code is, the easier it is to effect changes painlessly. Now we are going to take that “nicer” code (compared to the first version) and put Unity in the mix. Note you can get Unity with the Enterprise Library from p&p group.
As I said in part 1
what I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job. If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
Applying Unity
The first step to using Unity is setting it up it, to do that you need to add three references to your solution (highlighted below):
Unity has two configuration options, one in code and one in an external configuration file (normally your app/web.config). They both have a use but for this series I will use the configuration file which means you also need to add a reference to:
I tend to find that the config file route is what I use in production while the code one is what I use in unit tests (normally to override config file settings).
Next add the references to your code:
using System.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
Now in my main method of my application I am going to create an instance of an UnityContainer (line 21 below). This is effectively a magic bag, where we put our hand in and say what we want and pull it out - just like Mary Poppins had. Before we can do that we need to tell it to read the configuration information (lines 23 and 24 below) and then we retrieve the logger (line 26 below) from the magic bag. Note that we are NOT creating an instance of a logger on line 10 below as we did before, the act of pulling the logger out of the bag creates it.
1: using System;
2: using System.Configuration;
3: using Microsoft.Practices.Unity;
4: using Microsoft.Practices.Unity.Configuration;
5:
6: namespace BigSystem
7: {
8: class Program
9: {
10: static ILogger logger;
11:
12: static void DoSomething(string Username)
13: {
14: logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
15: Console.WriteLine("Hello {0}", Username);
16: logger.LogThis("DoSomething Completed");
17: }
18:
19: static void Main(string[] args)
20: {
21: IUnityContainer container = new UnityContainer();
22:
23: UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
24: section.Containers.Default.Configure(container);
25:
26: logger = container.Resolve<ILogger>();
27:
28: logger.LogThis("Application started");
29: DoSomething("Robert");
30: Console.ReadKey();
31: logger.LogThis("Application Completed");
32: }
33: }
34:
35: public interface ILogger
36: {
37: void LogThis(string Message);
38: }
39:
40: public class DebugLogger : ILogger
41: {
42: public void LogThis(string Message)
43: {
44: System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
45: }
46: }
47:
48: public class ConsoleLogger : ILogger
49: {
50: public void LogThis(string Message)
51: {
52: Console.WriteLine("{0}: {1}", DateTime.Now, Message);
53: }
54: }
55: }
Lastly we need to dive into the app.config (add one now if you are following at home) and fight the tangled web of Unity configuration.
Unity Config
We start off by adding a configSection to tell the framework how to handle the new section for Unity (this is lines 3 to 5). Then on line 7 we open our unity tag and the first thing in there is the typeAliases. I recommend using type aliases as they allow you to centrally link a type (like BigSystem.ILogger) to a friendly name. In our example below it’s overkill we could’ve just used the types directly on line 16 (I’ll cover that in a second) but as your solution grows doing find and replace for types is a pain and having this alias system will make life easier. So lines 9 and 10 alias my class and interface to a friendly name.
Now line 13 is where the meat comes in, we open the containers tag which allows up to setup our container which is just a named group of settings. We have one container so we do not need to name it, and in there is the types tag (line 15) which allows us to map what interface to what class, so we we call container.Resolve<ILogger> (line 26 in the code above) it knows what class to return.
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <configSections>
4: <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
5: </configSections>
6:
7: <unity>
8: <typeAliases>
9: <typeAlias alias="Logger" type="BigSystem.DebugLogger, BigSystem"/>
10: <typeAlias alias="ILogger" type="BigSystem.ILogger, BigSystem"/>
11: </typeAliases>
12:
13: <containers>
14: <container>
15: <types>
16: <type type="ILogger" mapTo="Logger" />
17: </types>
18: </container>
19: </containers>
20: </unity>
21: </configuration>
So if you run the code it will actually do the logging to the Output window in Visual Studio!
Then if we change line 9 above as such it will output to the console!
<typeAlias alias="Logger" type="BigSystem.ConsoleLogger, BigSystem"/>
This is not super cool because we just made it possible to externally say what class it should use without a recompile of code. You still need to have all the classes in your code already (think ahead) and we have made the logging any better than before. We will really get this improved in part 4 but for now we are moving in the right direction, even if it doesn’t seem like it.
Tripping over logs: A story of Unity - Part 1
Welcome to the first part in my series on using Unity, which is a Dependency Injection or Inversion of Control tool/framework/thing from the p&p group. It’s a big and (over) complicated topic so if what I have just said means nothing, fear not for it will all make sense soon. I have broken this into a series to make it easier to digest. What I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job (part 6 has links). If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
The Problem
A few years back I was developing an enterprise solution for a bank which integrated MSCRM into a number of systems, and so I needed to make sure I did logging (that’s what enterprise apps have, right?). Initially I had a simple “write to text file” logging system, which worked fine on my machine (if you can see what the problem is in that sentence you been developing too long). That is until we started testing and we ramped up the usage and I hit concurrency and locking issues. That prompted me to rip out all the logging and use the logging within System.Diagnostics.Trace as it seemed like it would work better, and it did for a long time. At some point I was pulled back to project (I left it for a long time) and needed to change the logging to use the p&p Enterprise Library logging. It was only at this point did I stop calling the System.Diagnostics.Trace code directly in each place for logging and start calling a custom method. This is what it sort of looked liked, excepted I had lots more parameters on the logging (level of message, source component etc…) and we logged every time something changed not just entry and exit:
public void DoSomething()
{
LogThis("Do Something Start");
...
LogThis("Do Something End");
}
When I changed it out I did some number crunching and realised that 40% of all the lines of code was these calls to logging! I remember thinking that was well done and how proud I was of my logging skills. Now days I look back at that as ridiculous. Not the fact I did logging, just how much code was spent on it and how tightly bound it was. So how could I do it better now days, well through a principal called Dependency Injection and an implementation of it called Unity (from the p&p team in their Enterprise Library).
Note: I am using the example of logging as the problem to solve, but really DI can be used for anything.
I must admit that Unity though is anything but simple, it is one of the hardest things I have had to learn in a while. What made it tough was understanding the documentation which enables you to learn Unity, but you need to understand Unity first to understand the documentation, talk about catch 22. It’s odd because the other blocks in EntLib are easy to get up and running but with Unity the samples are confusing and the help more so. In the end, some search kung fu + luck + patience seems to be what is needed to get through it. That said I feel a simple series of blog posts may help others out, which is what this is ;)
Starting Block
A special note is that this series is HEAVY with code and makes the articles look long, but actually I am repeating the code each time so you can compare the changes easily.
So lets start with a simple application as our base which will make it clear what we have and what we will change to get Unity working. As those who attend any of my sessions know I love console apps so I’ve whipped up a simple on that writes to the screen. The code looks like this:
using System;
namespace BigSystem
{
class Program
{
static void DoSomething(string Username)
{
Console.WriteLine("Hello {0}", Username);
}
static void Main(string[] args)
{
DoSomething("Robert");
Console.ReadKey();
}
}
}
And the solution like this (note the references - super clean):
Now using my “Enterprise Skills” from earlier, we add some logging like so:
static void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
static void DoSomething(string Username)
{
LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
LogThis("Application Completed");
}
Right, so that code is not bad. It works which makes the (imaginary) customer is happy. This code is not good either, because if we want to change anything it’s a big issue, likely “solved” by a find and replace. A better route would be to take the logging out and define it in a separate class that inherits from an interface. This means when we create the class we can change that one place and all the code is effected. So that would look like this:
class Program
{
static ILogger logger = new DebugLogger();
static void DoSomething(string Username)
{
logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
logger.LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
logger.LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
logger.LogThis("Application Completed");
}
}
public interface ILogger
{
void LogThis(string Message);
}
public class DebugLogger : ILogger
{
public void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
}
Note the constructor for logger and the interface and class below. The reason this is powerful is if I wanted to change this to output to the console I could spin up a new class, and just change the constructor for logger, as in below:
class Program
{
static ILogger logger = new ConsoleLogger();
static void DoSomething(string Username)
{
logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
logger.LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
logger.LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
logger.LogThis("Application Completed");
}
}
public interface ILogger
{
void LogThis(string Message);
}
public class DebugLogger : ILogger
{
public void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
}
public class ConsoleLogger : ILogger
{
public void LogThis(string Message)
{
Console.WriteLine("{0}: {1}", DateTime.Now, Message);
}
}
This is great, except to change the type of logger I need to change the code. Wouldn’t it be better to
- Be able to specify in a configuration file what should be used?
- Instead of instantiating a logger (like with the constructor), I could have a bag where code could reach into and ask for a logger?
This is what Unity provides at a basic level and we will implement in the next post, but trust me it goes much further and becomes much more powerful.
Search better
Something I have always thought of as a secret weapon in my skills is that search the Google has generally yielded good results or I find I am alone in my problem. I have found that others do not do this as well, often times they search - get nothing, come to me for help, I search and get what they need. Regardless there is a interesting game from MS research which shows you a page and you search for it (backwards to the norm) and score points for how high it appeared in the rank and if you didn’t use common phrases.
My gripe with it is that it has a timer (how many can you do in set time) and since it needs to load the pages, us poor South Africans with no bandwidth it makes the game go slower. I figure I could get 4 or 5 more pages in with decent bandwidth. Oh well, check out PageHunt
Thanks to Alfred for the heads up.
S.A. Architect Community Website Stats - December 2008
Since I took over the operations side of the S.A. Architect site I have kept stats on how well it is doing. The stats are based off of IIS log parsing as well as off of the stats information from SharePoint (which powers it). I have decided to share these each month with the community.
Some notes on it:
- Distinct Users means people which can be identified through logs/tracking to be unique (it’s not an exacting science so there may be people who are counted more than once while others are grouped together as they come from behind a proxy). They are not members and can include things like search bots. I don’t care about the number too much on this but rather the trend.
- Registered Members are people who have completed the registration form on the website.
You can definitely see that people are on holiday over December as the number of requests/users etc… have all dropped, we did however gain 4 new members in the last month!
Mac & IPhone Developers Wanted
Rein is organizing the first CocoaHeads meeting in Africa. If you are interested in development on Mac OSX or IPhone then you have to see http://www.noggin.co.za/2008/12/cocoaheads-johannesburg/
What is a CocoaHead
CocoaHeads is a group devoted to discussion of Apple Computer's Cocoa Framework for programming on MacOS X. During monthly meetings, members present on their projects and offer tutorials on various programming topics.
It’s at the BB&D offices, so I may decide to pop in myself and ask questions like “how does this compare with .Net or Java frameworks?” and “why should I bother when I have Mono/Silverlight/Flash/Air/Java etc…?”, which I am sure will lead to me being beaten by a Mac developer ;)
Installing MSMQ in Domain Mode on Windows Server 2008
Yesterday I needed to install MSMQ on my laptop which runs Windows Server 2008, which wasn’t as logical as it first appeared. I simply fired up the Server Manager tool, went to features, selected Message Queuing and clicked next. However my code kept giving me an error: “This operation is not supported for Message Queuing installed in workgroup mode.”
So I went to find out what this mean, and it turns out MSMQ has two modes workgroup and domain. Domain is the “yes you can” mode where everything works while workgroup has restrictions:
The following restrictions exist when using Message Queuing in workgroup mode:
- Computers in workgroup mode require direct connectivity with a destination computer, and only support direct message transmission. Messages sent by such computers cannot be routed.
- There is no access to Active Directory Domain Services. As such, you can create and manage private queues only on a local computer. You can view the list of private queues on another computer, and the messages in them, using the Computer Management snap-in. For information about managing queues on remote computers, see Verwalten von Warteschlangen auf anderen Computern. You cannot view or manage public queues or any other information in Active Directory Domain Services. You can, however, send messages to or retrieve messages from private queues if there is direct connectivity.
- Internal certificates cannot be used for sending authenticated messages; an external certificate must be used. For more information about user certificates, see User Certificates.
- Messages cannot be encrypted. For more information about encryption, see Encryption for Message Queuing.
- There is no support for dependent clients. For more information about restrictions on the deployment of dependent clients, see Dependent Clients.
- Cross-platform messaging is not supported. For more information, see Cross-Platform Messaging.
That is taken from the helpful TechNet page Deploying in Workgroup Mode, which also states:
The default installation setting is that the directory service Integration feature is installed
Oddly enough though that is NOT what I got, in fact when I went to check Directory Service Integration had not been installed even though I am on a domain (and was connected to the network at the time)! To fix it, I had to go back to the Server Manager Tool, Features, Message Queuing and manually select it.
TFS Branching Guidance is Out
Very late notice from me (been sitting in my inbox for 2 weeks) but the TFS branching guidance is now out on CodePlex: http://dotnet.org.za/willy/archive/2008/12/20/vsts-branching-guidance-ii-a-great-guidance-release.aspx
Interesting it’s the 25th highest download on CodePlex at the moment too! Guess it shows that it isn’t just me and Ryan spending a lot of time trying to figure out the perfect strategy!