Dependency Injection Failure

Sep 18, 2009 at 1:17 AM

Hi all,

I have 2 interfaces, one has depedency of another. But when I use container to resolve it throws exception. Here is my code snip.

interface IFileNameProvider {
	string GetFileName();
}

class RandonFileName : IFileNameProvider {
	public string GetFileName() {
		return "Random.txt";
	}
}

class SequentialFileName : IFileNameProvider {
	public string GetFileName() {
		return "Sequential.txt";
	}
}
Above are my first interface to provide file naming function.
interface IFileSaver {
	bool SaveFile(string content);

	IFileNameProvider FileNameProvider {
		get;
		set;
	}
}

class CsvFileSaver : IFileSaver {
	public bool SaveFile(string content) {
		string filename = FileNameProvider.GetFileName();

		return true;
	}

	[Dependency]
	public IFileNameProvider FileNameProvider {
		get;
		set;
	}
}

class BinaryFileSaver : IFileSaver {
	public bool SaveFile(string content) {
		string filename = FileNameProvider.GetFileName();
		return false;
	}

	[Dependency]
	public IFileNameProvider FileNameProvider {
		get;
		set;
	}
}
Above is my 2nd interface to do the actual file save job.
 
In my main program, I have following code and there is no config file at all.
	class Program {
		static void Main(string[] args) {
			IUnityContainer container = new UnityContainer();
			container.RegisterType<IFileNameProvider, RandonFileName>("RandonName");
			container.RegisterType<IFileNameProvider, SequentialFileName>("SequentialName");
			container.RegisterType<IFileSaver, CsvFileSaver>("SaveCsv");
			container.RegisterType<IFileSaver, BinaryFileSaver>("SaveBin");

			IFileSaver saver = container.Resolve<IFileSaver>("SaveBin");
			saver.SaveFile("text");
		}
	}
When I run the application I got exception like below. Anybody knows what is wrong?
Microsoft.Practices.Unity.ResolutionFailedException was unhandled
  Message="Resolution of the dependency failed, type = \"UnityTest.IFileSaver\", name = \"SaveBin\". Exception message is: The current build operation (build key Build Key[UnityTest.BinaryFileSaver, SaveBin]) failed: The value for the property \"FileNameProvider\" could not be resolved. (Strategy type BuildPlanStrategy, index 3)"
  Source="Microsoft.Practices.Unity"
  NameRequested="SaveBin"
  TypeRequested="IFileSaver"
  StackTrace:
       at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
       at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name)
       at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)
       at Microsoft.Practices.Unity.UnityContainerBase.Resolve[T](String name)
       at UnityTest.Program.Main(String[] args) in C:\Temp\UnityTest\UnityTest\Program.cs:line 16
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: Microsoft.Practices.ObjectBuilder2.BuildFailedException
       Message="The current build operation (build key Build Key[UnityTest.BinaryFileSaver, SaveBin]) failed: The value for the property \"FileNameProvider\" could not be resolved. (Strategy type BuildPlanStrategy, index 3)"
       Source="Microsoft.Practices.ObjectBuilder2"
       BuildKey="Build Key[UnityTest.BinaryFileSaver, SaveBin]"
       ExecutingStrategyIndex=3
       ExecutingStrategyTypeName="BuildPlanStrategy"
       StackTrace:
            at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
            at Microsoft.Practices.ObjectBuilder2.Builder.BuildUp(IReadWriteLocator locator, ILifetimeContainer lifetime, IPolicyList policies, IStrategyChain strategies, Object buildKey, Object existing)
            at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
       InnerException: System.InvalidOperationException
            Message="The value for the property \"FileNameProvider\" could not be resolved."
            Source="Microsoft.Practices.ObjectBuilder2"
            StackTrace:
                 at Microsoft.Practices.ObjectBuilder2.DynamicMethodPropertySetterStrategy.ThrowOnFailedPropertyValueResolution(Exception inner, String propertyName)
                 at BuildUp_UnityTest.BinaryFileSaver(IBuilderContext )
                 at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
                 at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
                 at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
            InnerException: Microsoft.Practices.ObjectBuilder2.BuildFailedException
                 Message="The current build operation (build key Build Key[UnityTest.IFileNameProvider, null]) failed: The current type, UnityTest.IFileNameProvider, is an interface and cannot be constructed. Are you missing a type mapping? (Strategy type BuildPlanStrategy, index 3)"
                 Source="Microsoft.Practices.ObjectBuilder2"
                 BuildKey="Build Key[UnityTest.IFileNameProvider, null]"
                 ExecutingStrategyIndex=3
                 ExecutingStrategyTypeName="BuildPlanStrategy"
                 StackTrace:
                      at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
                      at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
                      at BuildUp_UnityTest.BinaryFileSaver(IBuilderContext )
                 InnerException: System.InvalidOperationException
                      Message="The current type, UnityTest.IFileNameProvider, is an interface and cannot be constructed. Are you missing a type mapping?"
                      Source="Microsoft.Practices.ObjectBuilder2"
                      StackTrace:
                           at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context)
                           at BuildUp_UnityTest.IFileNameProvider(IBuilderContext )
                           at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
                           at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
                           at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
                      InnerException:
Sep 18, 2009 at 12:44 PM

You only have named types registered so the dependency property cannot be resolved, i.e. you would need something as follows:

                   container.RegisterType<IFileNameProvider, RandonFileName>();

I'm just barely rolling up my sleeves on the latest drop (so there may be yet a better way)
but you can do the following (unit test passes) using the latest drop (Unity 2.0):

[TestMethod]
public void canUseNamedProperty()
{
    IUnityContainer container = new UnityContainer();
    container.RegisterType<IFileNameProvider, RandonFileName>("RandonName");
    container.RegisterType<IFileNameProvider, SequentialFileName>("SequentialName");
    container.RegisterType<IFileSaver, CsvFileSaver>("SaveCsv");
    container.RegisterType<IFileSaver, BinaryFileSaver>("SaveBin",
        new InjectionProperty("FileNameProvider",
            container.Resolve<IFileNameProvider>("RandonName")));

    IFileSaver saver = container.Resolve<IFileSaver>("SaveBin");
    saver.SaveFile("text");
    Assert.AreEqual("Random.txt",saver.FileNameProvider.GetFileName());
}

 

Sep 18, 2009 at 2:41 PM

Thanks,

That makes sense to me.