IsRegistered throws Exception

Feb 10, 2010 at 12:32 PM

Howdy!

I was just playing with the 2.0 Beta because I need IsRegistered(), but I encountered a problem:

Why does the IsRegistered() call in the following snippet throw an InvalidCastException?

 

using System;
using Microsoft.Practices.Unity;

namespace Repro
{
	public interface IFoo
	{
		int I { get; set; }
		void F();
	}
	
	public class Foo: IFoo
	{
		public Foo( IBar bar )
		{
			bar.G();
			Console.WriteLine( bar.Text );
		}
		
		public int I { get; set; }
		
		public void F()
		{
			Console.WriteLine( "Foo::F" );
		}
	}
	
	public interface IBar
	{
		string Text { get; set; }
		void G();
	}
	
	public class Bar: IBar
	{
		public string Text { get; set; }
		
		public void G()
		{
			Console.WriteLine( "Bar::G" );
		}
	}
	
	public interface IEvil
	{
	}
	
	public class Entry
	{			
		static void Main()
		{
			Console.WriteLine( "Program start." );
			
			IUnityContainer uc = new UnityContainer();
			uc.RegisterType<Bar>();
			uc.RegisterType<IFoo, Foo>
			(
				new InjectionConstructor( new ResolvedParameter( typeof( Bar ) ) ),
				new InjectionProperty( "I", 33 )
			);
			
			Bar bar = new Bar();
			bar.Text = "oergl";
			
			IFoo foo = uc.Resolve<IFoo>( new ParameterOverrides{ {"bar", bar } } );
			foo.F();		
			Console.WriteLine( foo.I );
			
			bool isReg = uc.IsRegistered<IEvil>();
			//bool isReg = uc.IsRegistered<IFoo>();
			
			Console.WriteLine( "Program end." );
			Console.ReadKey();
		}
	}
}

The exception is thrown here:

private LifetimeManager GetLifetimeManager(IPolicyList policies)
        {
            var key = new NamedTypeBuildKey(MappedToType, Name);
            return (LifetimeManager)policies.Get<ILifetimePolicy>(key);
        }

Regards,

void*

 

Feb 10, 2010 at 6:20 PM

Stupidity on my part, unfortunately.

The issue is that when looking up the lifetime type, it's casting the currently available lifetime policy to LifetimeManager. Unfortunately, the default lifetime (TransientLifetimePolicy) isn't actually a LifetimeManager (long, not very interesting story as to why).

I've fixed this already in the current codebase, I should be doing another source drop in the next week or two, and the fix will be in the next beta.

The workaround for now would be to explicitly register that object with the TransientLifetimeManager. The real fix was to change the default, in the file LifetimeStrategy.cs, line 83. Change:

 

policy = new TransientLifetimePolicy();

to

 

policy = new TransientLifetimeManager();

This was already logged as codeplex bug #6997 - I've closed it as fixed, so no need to log it again.

 

 

 

Feb 11, 2010 at 3:34 PM

Hi Chris,

thx for the quick feedback!

I was wondering why it worked if I used design time (XML) config, but that apparently explicitly registers those types with the TransientLifetimeManager... :)

Regards,

void*