-
"Parameter count mismatch" calling Resolve<T>()
I was seeing this exception being thrown in some code recently:
System.Reflection.TargetParameterCountException: Parameter count mismatch. at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index) at Castle.Core.ReflectionBasedDictionaryAdapter..ctor(Object target) at Castle.MicroKernel.DefaultKernel.Resolve[T](Object argumentsAsAnonymousType)
The original source line was something like this:
IDictionary<string, object> args = new Dictionary<string, object>(); args.Add( “paramName”, “value” );
_kernel.Resolve
( args ); That all looks fine, and let’s assume the Something class has indeed a constructor with a string parameter named ‘paramName’. So why isn’t it working?
I should have noticed the clue[1] in the stack trace, but was sure I had identical code elsewhere that was working correctly, so it had me stumped. It was only after taking a break from the code, then playing around with a very simple test project that I realised that while there is a method Resolve
(IDictionary), that’s not the one that was being called here. Why? Because instead of using [var](http://msdn.microsoft.com/en-us/library/bb383973.aspx), I’d declared the variable to be an [IDictionary](http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx)<string, object> – and surprisingly that interface does not imply you implement [IDictionary](http://msdn.microsoft.com/en-us/library/system.collections.idictionary.aspx) (the non-generic version). When I went back and checked other instances of the code that were working, sure enough I was using var and because Dictionary<> does implement both IDictionary<> and IDictionary it was working as expected.
[1] The clue was the type and parameter name for Resolve - “Object argumentsAsAnonymousType” is obviously not the same as IDictionary!
-
Avoiding static references to an IoC container
It seems quite common for applications to employ a static class to encapsulate the Inversion of Control container. A simple example of such a class might be:
public static class IoC { private static IWindsorContainer _container = new WindsorContainer();
public static T Resolve<T>() { return \_container.Resolve<T>(); } }
While the normal practise would be to inject dependencies through the constructor, there are times where you may need to pass extra arguments as part of the Resolve() method. You might end up with a method such as this:
public class SomeClass : ISomeClass { public SomeClass() { } public void SomeMethod(string name) { if (name == "david") { var class1 = IoC.Resolve<IClass1>(); } else { var class2 = IoC.Resolve<IClass2>(); } } }
This works, but because of the tight coupling to the IoC class, it isn’t ideal. It also makes it harder to test as you are going to have to ensure that WindsorContainer gets configured appropriately.
A better solution is to add a dependency in the contructor for IKernel. If this class is resolved via the container, then it will resolve IKernel to a reference of the current Windsor MicroKernel object (which WindsorContainer inherits from). You can then use the reference to kernel to call its Resolve() method. Having the kernel injected now means it is now elementary to pass in a mock in your test code, mitigating the need to have all your castle.config configuration for your unit tests.
public class SomeClass : ISomeClass { private IKernel _kernel; public SomeClass(IKernel kernel) { _kernel = kernel; }
public void SomeMethod(string name) { if (name == "david") { var class1 = \_kernel.Resolve<IClass1>(); } else { var class2 = \_kernel.Resolve<IClass2>(); } } }
-
Examples of log4net PatternLayout output
log4net has a lot of options when it comes to defining what you write to your log. While all the patterns are documented, it is useful to see a sample output from some code. Here is the output produced from some of the patterns available:
Pattern Class ‘BaseClass’ Class ‘SubClass’ appdomain log4netPatterns.vshost.exe log4netPatterns.vshost.exe date 2009-05-24 16:37:26,578 2009-05-24 16:37:26,640 file C:\Dev\GoogleCode-Gardiner\trunk\Log4netPatterns\log4netPatterns\Program.cs C:\Dev\GoogleCode-Gardiner\trunk\Log4netPatterns\log4netPatterns\Program.cs identity location log4netPatterns.BaseClass`1.MyMethod(C:\Dev\GoogleCode-Gardiner\trunk\Log4netPatterns\log4netPatterns\Program.cs:32) log4netPatterns.SubClass.MyMethod(C:\Dev\GoogleCode-Gardiner\trunk\Log4netPatterns\log4netPatterns\Program.cs:49) level DEBUG DEBUG line 32 49 logger log4netPatterns.BaseClass`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] log4netPatterns.SubClass message BaseClass SubClass method MyMethod MyMethod property {log4net:HostName=morgan} {log4net:HostName=morgan} timestamp 45968 46015 thread 2116 2116 type log4netPatterns.BaseClass`1 log4netPatterns.SubClass username MORGAN\David MORGAN\David utcdate 2009-05-24 07:14:41,468 2009-05-24 07:14:41,515 Of particular interest is the difference between logger and type. For the SubClass class, they result in the same output, but for the BaseClass logger is a lot more verbose (especially if your generic type happens to be from a strongly-signed assembly!). Using logger will give more detailed information but at the expense of larger log files.
Methodology
Because some of the patterns vary their output if you are in a base class or an inherited class, I created a simple class hierarchy, and also included use of generics.
public class BaseClass<T> { private ILog _log; public BaseClass() { _log = LogManager.GetLogger(typeof (BaseClass<T>)); } public virtual string MyMethod(T stuff) { _log.Debug("BaseClass"); return "ha"; } } public class SubClass : BaseClass<string> { private ILog _log; public SubClass() { _log = LogManager.GetLogger(typeof (SubClass)); } public override string MyMethod(string stuff) { _log.Debug("SubClass"); return "ho ho"; } }
The project that included this code was strongly signed, to allow any effect this might cause to be evident.