Registering generic types without specifying 'T'

Jun 25, 2008 at 9:07 PM
I read this post and it's similar to what I'd like to do (http://www.codeplex.com/unity/Thread/View.aspx?ThreadId=24985).

I have an interface IFoo<T>. 
I have a single concrete implementation Foo<T>.  

What I'd like to do is the following (in VB.NET, no less!!)

Dim container = new UnityContainer()
container.RegisterType(Of IFoo(Of), Foo(Of))

Then I'd like to be able to resolve that registered interfaced like so:

dim obj = container.Resolve(Of IFoo(Of String))()
or
dim obj = container.Resolve(Of IFoo(Of Address))()

However, when I do this I get a syntax error.  I'm totally aware that this could be my total lack of VB.NET knowledge, but is this type of open generic type registration possible with Unity?
Jun 25, 2008 at 9:09 PM
Hmm... looks like it is my lack of VB.NET kung foo!

http://davidhayden.com/blog/dave/archive/2008/03/25/UnityDependencyInjectionOpenGenericTypes.aspx

I hope this isn't one of those C# can do it, but VB.NET can't things... :-(
Jun 25, 2008 at 9:19 PM
Hi again... just chatting with myself here.   For those who find this post in the future I did find a way to accomplish this open generic type registration.

If I register using the non-generic methods that UnityContainer exposes, I can do it.

container.RegisterType(GetType(IFoo(Of), Foo(Of))
Jun 26, 2008 at 3:00 PM
Edited Jun 26, 2008 at 3:03 PM
I've tried the same thing with IDictionary:

unityContainer.RegisterType(

typeof(IDictionary<>), typeof(Dictionary<>));

but I get the following error:

"Error 1 Using the generic type 'System.Collections.Generic.IDictionary<TKey,TValue>' requires '2' type arguments"

Is there a way to do this using IDictionary?  (more importantly, for any generic that takes more than one type)

 

 

Jun 26, 2008 at 5:32 PM
Your syntax is wrong. Try:

container.RegisterType(typeof(IDictionary<,>), typeof(Dictionary<,>));

Note the comma inside the angle brackets.
Jul 24, 2008 at 1:10 PM
Edited Jul 24, 2008 at 1:12 PM
Hi,

I get an exception when using ....

container.RegisterType(typeof(IDictionary<,>), typeof(Dictionary<,>));

The exception is...

"Resolution of the dependency failed, type = \"IDictionary`2\", name = \"\". Exception message is: The current build operation (build key Build
Key[System.Collections.Generic.Dictionary`2[System.String,System.String], null]) failed: The current build operation (build key Build
Key[System.Collections.Generic.Dictionary`2[System.String,System.String], null]) failed: The type Dictionary`2 has multiple constructors of length
2. Unable to disambiguate.

When I attempt...

IDictionary<string,string> myExampleDictionary = container.Resolve<IDictionary<string, string>>();

I thought the following code should enable unity to resolve the correct constructor (in this case the parameterless constructor Dictionary<string,string>()) however that does'nt seem to work?

container.Configure<InjectedMembers>().ConfigureInjectionFor(typeof(Dictionary<,>),new InjectionConstructor());

I'm new to using the UnityContainer so maybe i'm missing something obvious, however any help would be greatly appreciated? Does anyone know any good adavanced books that could help?

Cheers,

Andy


Jul 24, 2008 at 5:44 PM
Andy,

There are no books that'll help, Unity is a little too new for publishers to have caught up yet.

Unfortunately, you've run into a bug in our generics handling. This is currently fixed in our internal version, but it'll be a little while before we can get the bits out. In the meantime, as a workaround you could do something like this instead:

public class WorkaroundDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public WorkaroundDictionary() { }
}

container.RegisterType(typeof(IDictionary<,>), typeof(WorkaroundDictionary<,>));

The WorkaroundDictionary only has the default constructor so it'll inject no problem. Since the rest of your app is written in terms of IDictionary, when we get the fixed version done you can just replace the registration with the real Dictionary class, throw out the workaround, and everything will still just work.

Sorry about the bug, it'll be fixed soon!

-Chris
Jul 25, 2008 at 7:48 AM
Hi Chris,

Many thanks for the information & workaround.

Looking forward to future releases!

Cheers,

Andy
Jul 25, 2008 at 3:39 PM
Edited Jul 25, 2008 at 3:41 PM

I'm trying to use generics in a little different fashion and am having trouble.  I have the following declaration
 
public class ImageStrategy : IUIObjectStrategy<Image>

I'd like to be able to map the concrete ImageStrategy to  IUIObjectStrategy<Image>.

I want to be able to execute the following code and get back an "ImageStrategy":
   
IUIObjectStrategy<Image> strat = container.Resolve<IUIObjectStrategy<Image>>();

I'll also have other strategies like:

public class RectangleStrategy : IUIObjectStrategy<Rectangle>
etc...

Is this possible?  Maybe I'm going about this the wrong way.  Please advise if you can.

- Russell
 

 

Jul 25, 2008 at 4:35 PM
It looks like I've found a way to do this:

<

 

typeAlias alias="IUIObjectStrategy" type="ReportDesigner.IUIObjectStrategy`1, ReportDesigner" />
<
typeAlias alias="ConcreteImageStrategy" type="ReportDesigner.ImageStrategy, ReportDesigner" />
<
typeAlias alias="ConcreteRectangleStrategy" type="ReportDesigner.RectangleStrategy, ReportDesigner" />

......

 

<

 

types>
    <type type="IUIObjectStrategy" mapTo="ConcreteImageStrategy" name="image"/>
    <
type type="IUIObjectStrategy" mapTo="ConcreteRectangleStrategy" name="rectangle"/>
</
types>

.....

 

 

IUIObjectStrategy<Image> imageStrat = container.Resolve<IUIObjectStrategy<Image>>("image");
IUIObjectStrategy<Rectangle> rectStrat = container.Resolve<IUIObjectStrategy<Rectangle>>("rectangle");

 

Aug 19, 2008 at 12:13 AM
Just wanted to let folks know we've released the bits that have the generics fixes in them. Take a look and let us know what you think. It's checked into codeplex source control.