15

Closed

Container.BuildUp() throws InvalidOperationExcetption when the object instance does not have a Public constructor.

description

<p>Hello, - I had previously posted this as a workitem on enterprise library codeplex: http://entlib.codeplex.com/workitem/28939 - but to outline the issue and add some more detail:-</p> <p>&nbsp;</p> <p>Unity v1.2 let you BuildUp() against an existing instance, and it would inject the dependencies into that instance (via method / property injection), even though the instances type in question did not have a public constructor. Which makes perfect sense to me, as why would unity possibly need to know about a constructor when all its doing is injecting into an existing instance all the time!</p> <p>&nbsp;</p> <p>Unity 2 throws an exception if you BuildUp() there is no public constructor. I have outlined this in the tests.</p> <p>&nbsp;</p> <p>I understand from ctavares comment on previous workitem at entlib codeplex, that when unity encounters a type it tries to find a public constructor &quot;in case&quot; you need to do a resolve() later on down the line.</p> <p>If this is correct, then call me a simpleton, but in this instance this optimisation feature of unity seems a waste of resources and a breaking change from v1.2 that will mean that I have to give all my classes public constructors, even though unity will never actually need to construct a single one. Its common to have private / internal constructors especially when your object instances are obtained through factories for example.</p> <p>&nbsp;</p> <p>I am guessing a solution here would be some mechanism by which to tell unity that for particular types, it can disable its &quot;public constructor&quot; checks as unity will never be asked to create / Resolve() an instance of that type. BuildUp() would then succeed for those types - as it will not have to check for a public constructor as it will know it will never be needed.</p> <p>&nbsp;</p> <p>Kind Regards</p> <p>Darrell</p>

file attachments

Closed Aug 7, 2012 at 1:06 AM by
Fixed

comments

hkoukkides wrote Oct 11, 2010 at 5:41 PM

Working with 3rd party libs becomes a nightmare with this.

ctavares wrote Nov 4, 2010 at 4:06 AM

Somewhat larger issue here - looks like Buildup in general for non-constructable classes has some issues. Also fails for classes that have ambiguous constructors.

mrpmorris wrote Nov 5, 2010 at 9:27 AM

I've hit this myself.

mrpmorris wrote Nov 5, 2010 at 9:27 AM

Adding comment so that I can subscribe to replies.

FredYu wrote Nov 10, 2010 at 8:26 PM

I had the the issue. Is there any work around without declaring public constructor?

chrishowle wrote Nov 24, 2010 at 5:02 PM

I'm having the same problem. Having to stay with 1.2 for now as there is no work around for us.

mrpmorris wrote Nov 25, 2010 at 9:24 AM

I created this IUnityContainer helper class with a "CallInjectionMethod" method on it. Seems to work okay for me as a workaround.

http://blog.peterlesliemorris.com/archive/2010/11/24/unity.buildupndashambiguous-constructor.aspx

When Unity is fixed you can just do a find/replace.

solidgranite wrote Dec 13, 2010 at 3:49 AM

I came across this when I upgraded also. I believe it is a bug in the Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy class.

The new Unity codebase adds a call to "GuardTypeIsNonPrimitive" which throws an exception if there isn't a constructor (this method wasn't in 1.2). This method is called in the "PreBuildUp" method. Since this check method throws an exception, the code inside PreBuildUp is never allowed to execute the branch where selectedCtor equals null.

To fix this you need to modify the GuardTypeIsNonPrimitve method to ignore whether the selectedCtor is null (I imagine there is a good reason for this check however this was the only way I could get Unity 2 working for me!!!)

Modify GuardTypeIsNonPrimitive (in the source code) in the DynamicMethodConstructorStrategy.DynamicMethodConstructorStrategy class to this
    // Verify the type we're trying to build is actually constructable -
    // CLR primitive types like string and int aren't.
    private static void GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor)
    {
        var typeToBuild = context.BuildKey.Type;
        if(!typeToBuild.IsInterface)
        {
            // MODIFCATION 13/12/2010 BEGIN
            //if(typeToBuild == typeof(string) || selectedConstructor == null)
            // MODIFCATION 13/12/2010 END
            if (typeToBuild == typeof(string))
            {
                throw new InvalidOperationException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.TypeIsNotConstructable,
                        typeToBuild.Name));
            }
        }
    }
Hope this helps!!!

Amtiskaw wrote Apr 3, 2012 at 7:00 AM

This breaks the MSDN-specified method of using Unity Injection with ASP.NET:

http://msdn.microsoft.com/en-us/library/ff664534(v=pandp.50).aspx

Using this approach will now fail when it encounters a ResourceBasedLiteralControl.

gmelnik wrote Aug 2, 2012 at 9:57 PM

Fixed in the Aug 2012 update of Unity (2.1.505.2). Get it via NuGet. http://bit.ly/Ot1yLj