Is there a way to create an object with an Internal Constructor

Jan 13, 2011 at 7:30 PM

Hi,

I have the following issue. I have a public class with an internal constructor, and I would like to return an instance of that class with Unity :

 

public interface IFoo { }

public class Foo: IFoo {
     internal Foo() { }
}

When I do that now I get a Microsoft.Practices.Unity.ResolutionFailedException. The exception details are :

Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "IFoo", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type Foo cannot be constructed. You must configure the container to supply this value.

Here is a little bit of the stacktrace :

Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs: line 289
Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs: line 71
Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\StrategyChain.cs: line 110
Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\DynamicMethodBuildPlanCreatorPolicy.cs: line 48
Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\BuildPlanStrategy.cs: line 37
Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\StrategyChain.cs: line 110
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs: line 511
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs: line 515
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs: line 485
Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs: line 173
Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainerExtensions.cs: line 504

 

Is there any workaround for this? I have a feeling that trying to solve this with the InternalsVisibleAttribute will not work. Is there any other way?

Thanx,

Kostas

Jan 14, 2011 at 7:45 AM

Hrm... I've tested purely internal classes and they work, I'm not sure we tested public classes with internal constructors. However, in many of these cases you're actually running up against the .NET security model, which is very hard to work around in a sufficiently generic way.

Let's put it this way - you've explicitly said in your code "I want anyone to be able to call instances of this class, but only MY ASSEMBLY can create them." The runtime is going to enforce your intention.

One workaround would be to use InjectionFactory instead - since you define the factory method in the same assembly as the type in question, you can create the object in the factory method. You lose some of the autowiring features (you'll need to resolve stuff from the container yourself directly) but it'll work.