How to register primitive type?

Jun 3, 2009 at 7:42 PM

Hi!  I have a question.  I am trying to resolve a class that has a dependency to a class that has a constructor containing a string parameter.  It seems to have problem finding the string dependency.    

The question is how do we register primitive type like *string*.  Doesn't seem to work with container.RegisterType<System.String, System.String>();

Any help would be appreicated

Thanks,

Tony

public interface IMockUnityStringTarget
        {
            void Foo();
        }

        /// <summary>
        ///  This is a test dependent class it's needs the IMockUnityTarget Interface
        /// </summary>
        public class MockUnityStringTarget : IMockUnityStringTarget
        {
            public MockUnityStringTarget()
            {
            }

            public MockUnityStringTarget(System.String somestring)
            {
            }

            public void Foo()
            {
            }
        }

        /// <summary>
        ///  This is a test dependent class it's needs the IMockUnityTarget Interface
        /// </summary>
        public class MockUnityStringDependent
        {
            public MockUnityStringDependent(IMockUnityStringTarget stringtarget)
            {
            }

            public void Foo2()
            {
            }
        }

        [TestMethod]
        public void MockTest()
        {
            UnityContainer container = new UnityContainer();
            container.AddNewExtension<UnityBootstrapperExtension>();

            container.RegisterType<System.String, System.String>();
            Assert.IsTrue(container.IsTypeRegistered(typeof(System.String)));

            // resolve the mock dependent class, the target class will automatically inject into the dependency class
            MockUnityStringDependent ud = container.Resolve<MockUnityStringDependent>(); // <-- problem here.  It can't seem to find the string dependency.

        }

 

Error:

Test method SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture.UnitySingleTargetTest threw exception:  Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent", name = "". Exception message is: The current build operation (build key Build Key[SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent, null]) failed: The parameter stringtarget could not be resolved when attempting to call constructor SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent(SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+IMockUnityStringTarget stringtarget). (Strategy type BuildPlanStrategy, index 3) --->  Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent, null]) failed: The parameter stringtarget could not be resolved when attempting to call constructor SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent(SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+IMockUnityStringTarget stringtarget). (Strategy type BuildPlanStrategy, index 3) --->  System.InvalidOperationException: The parameter stringtarget could not be resolved when attempting to call constructor SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringDependent(SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+IMockUnityStringTarget stringtarget). --->  Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringTarget, null]) failed: The parameter somestring could not be resolved when attempting to call constructor SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringTarget(System.String somestring). (Strategy type BuildPlanStrategy, index 3) --->  System.InvalidOperationException: The parameter somestring could not be resolved when attempting to call constructor SEN.ContactCenter.Application.Framework.Administration.Service.Tests.UnityFixture+MockUnityStringTarget(System.String somestring). --->  Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[System.String, null]) failed: The parameter value could not be resolved when attempting to call constructor System.String(System.SByte* value, System.Int32 startIndex, System.Int32 length, System.Text.Encoding enc). (Strategy type BuildPlanStrategy, index 3) --->  System.InvalidOperationException: The parameter value could not be resolved when attempting to call constructor System.String(System.SByte* value, System.Int32 startIndex, System.Int32 length, System.Text.Encoding enc). --->  Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[System.SByte*, null]) failed: The type SByte* does not have an accessible constructor. (Strategy type BuildPlanStrategy, index 3) --->  System.InvalidOperationException: The type SByte* does not have an accessible constructor..

 

 

Jun 3, 2009 at 7:45 PM

Sorry.  missed one line from the code.  it should be.

 public interface IMockUnityStringTarget
        {
            void Foo();
        }

        /// <summary>
        ///  This is a test dependent class it's needs the IMockUnityTarget Interface
        /// </summary>
        public class MockUnityStringTarget : IMockUnityStringTarget
        {
            public MockUnityStringTarget()
            {
            }

            public MockUnityStringTarget(System.String somestring)
            {
            }

            public void Foo()
            {
            }
        }

        /// <summary>
        ///  This is a test dependent class it's needs the IMockUnityTarget Interface
        /// </summary>
        public class MockUnityStringDependent
        {
            public MockUnityStringDependent(IMockUnityStringTarget stringtarget)
            {
            }

            public void Foo2()
            {
            }
        }

        [TestMethod]
        public void MockTest()
        {
            UnityContainer container = new UnityContainer();
            container.AddNewExtension<UnityBootstrapperExtension>();

            container.RegisterType<System.String, System.String>();
            Assert.IsTrue(container.IsTypeRegistered(typeof(System.String)));

            container.RegisterType<IMockUnityStringTarget, MockUnityStringTarget>();

            // resolve the mock dependent class, the target class will automatically inject into the dependency class
            MockUnityStringDependent ud = container.Resolve<MockUnityStringDependent>();

        }

Jun 4, 2009 at 4:06 AM

RegisterType doesn't work with string, int, or the other CLR primitive types, because you can't legally say "new string()". You can use RegisterInstance:

container.RegisterInstance("SomeString");

And then anywhere you've got a dependency of type string, that string will be injected. But that's also probably not what you want to do, since a connection string is different from a file name is different from a user name, but they're all of type string.

What you need to do is, in your RegisterType call, specify which constructor you want, and what the value of the string will be. You use it by passing an InjectionConstructor object to RegisterType. If you want to use the default constructor instead of the one that takes a string, do this:

    container.RegisterType<IMockUnityStringTarget, MockUnityStringTarget>(new InjectionConstructor());

That says "Use the constructor for MockUnityStringTarget that takes zero arguments."

If you want to use the one that takes a string, do this:

    container.RegisterType<IMockUnityStringTarget, MockUnityStringTarget>(new InjectionConstructor("whatever string I want"));

You can also pass InjectionProperty objects to specify which properties to inject, or InjectionMethod to specify which methods to call.

By default, if you don't specify this, the container will look for the constructor with the most arguments, and attempt to create instances to pass as each one. Unfortunately, we can't just randomly new up a string, so in the case of primitives you need to be a little more explicit.

Hope this helps,

 

-Chris

 

Jun 4, 2009 at 7:46 PM

That helps a lot.

Thanks!

Tony