9. Constructor Injection

Constructor injection – so far inadvertantly we’ve been using setter inject to get our configuration information into our components… but you can also use constructors… the useful aspect of constructors is that it makes those parameters compulsory…
So lets take a look at the code for this post, first off there’s an interface for a service which takes care of encoding a string for us:

public interface IEncoder
    {
        string Encode(string source);
    }

And then we have no classes which implement this service, one we can use when testing to not encode things at all – and another which encodes a string using our particularly strong “silly” encryption…

NullEncoder.cs

public class NullEncoder : IEncoder
    {
        public string Encode(string source)
        {
            return source;
        }
    }

SillyEncoder.cs

public class SillyEncoder : IEncoder
    {
        private readonly char[] _mixedUp = "YACBDFEGIHJLKMONPRSQTUWVXZ".ToCharArray();

        public string Encode(string source)
        {
            var upperSource = source.ToUpper();
            var encoded = new char[source.Length];

            for (int i = 0; i < encoded.Length; i++)
            {
                encoded[i] = MapCharacter(upperSource[i]);
            }
            return new string(encoded);
        }

        private char MapCharacter(char ch)
        {
            if ((ch >= 'A') && (ch <= 'Z'))
            {
                return _mixedUp[ch - 'A'];
            }
            return ch;
        }
    }

When then have a class for sending messages (currently we just send it to the console, so we can print them out and paste them onto the back of postcards) … so lets have a look at that class:

public class SecretMessageSender
    {
        private readonly IEncoder _encoder;
        private readonly string _from;

        public SecretMessageSender(string from,IEncoder encoder)
        {
            _from = from;
            _encoder = encoder;
        }

        public void SendMessage(string to, string body)
        {
            Console.WriteLine("to: {0}\r\nfrom: {1}\r\n\r\n{2}", to, _from, _encoder.Encode(body));
        }
    }

Notice the lack of default constructor, and that the constructor also takes an instance of type IEncoder… now Unity is smart enough to do two things for us:

  • Throw an exception if we try to get an instance of SecreteMessageSender without having set the from configuration parameter.
  • Find the default implementation of the IEncoder registered in the container, and to supply that as the value for the second argument in the constructor. NB: Unlike castle however this is via explicitly configuring a non keyed instance. Unity does not follow the principle of convention over configuration by defaulting to the first registered instance of a type.

So lets have a look at the application itself:

private static void Main(string[] args)
        {
            IUnityContainer container = new UnityContainer();
            var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Containers.Default.Configure(container);

            var sender = container.Resolve<SecretMessageSender>("messageSender");
            sender.SendMessage("steve", "unity is great!");
            Console.Read();
        }

And finally our configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="unity"
                 type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration, Version=1.1.0.0,
                 Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </configSections>

    <unity>
        <containers>
            <container>
                <types>
                    <type type="MSUnity9.IEncoder, MSUnity9"
                         mapTo="MSUnity9.SillyEncoder, MSUnity9">
                    </type>

                    <type name="encoder.silly" type="MSUnity9.IEncoder, MSUnity9"
                         mapTo="MSUnity9.SillyEncoder, MSUnity9">
                    </type>

                    <type name="encoder.null" type="MSUnity9.IEncoder, MSUnity9"
                         mapTo="MSUnity9.NullEncoder, MSUnity9">
                    </type>

                    <type name="messageSender" type="MSUnity9.SecretMessageSender, MSUnity9">
                        <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
                            <constructor>
                                <param name="from" parameterType="System.String" >
                                    <value value="Mike@AardvarkBlogs.com" type="System.String"/>
                                </param>
                                <param name="encoder" parameterType="MSUnity9.IEncoder, MSUnity9" >
                                    <dependency/>
                                </param>
                            </constructor>
                        </typeConfig>
                    </type>
                </types>
            </container>
        </containers>
    </unity>

</configuration>

So you can see we’ve registered both implementations of the encoder but we have also registered a third implementation with no “name” key. We have to do this with Unity as if we specify a dependency of IEncoder and do not specify the name value Unity will not be able to resolve the implementation from the configuration. i.e. if you specify a name parameter you have to then use it.

So to achieve the same functionality as Windsor you must supply an extra registration without a key. It is also worth noting that if no default had been supplied in this way Unity would have tried to Resolve the implementation from the assembly, as we’re specifying an Interface that is impossible, but if we’d specified a concrete class in our constructor Unity would try to new up that class with null ctor params.

-we also register our message sender (with the required from parameter)… so what happens when we run it:
to: steve

from: Mike@AardvarkBlogs.com

CYSQLD IS ERDYQ!

Cool… but what if wanted to send an unencrypted message… well we have a few options:

  • Reference the implementation we specifically want to wire up to, using it’s identifier…(name property)
  • Reference the implementation we specifically want to wire up to, using it’s type
  • Change the default registration of IEncoder so that it’s mapTo attribute specifies the null encoder instead

Now it’s worth explaining the <dependency/> tag we see on our SecretMessageSender Constructor –

this is required to specify an object dependency. In it’s most primitive form with no attributes specified it tells Unity to look for an implementation of the Type of the parameter(IEncoder here) – which is why it finds our default implementation that’s mapped to the sillyencoder.

We can also specify a specific name i.e. <dependency name=”encoder.null”/> and Unity will then resolve that specific registration type

and lastly we can specify a type i.e. <dependency type=”MSUnity9.IEncoder, MSUnity9” /> which will force Unity to look specifically for that type in the config (again this would cause it to find our default registration)

So lets have a look at what happens when we use the name attribute…

<type name="messageSender" type="MSUnity9.SecretMessageSender, MSUnity9">
    <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
        <constructor>
            <param name="from" parameterType="System.String" >
                <value value="Mike@AardvarkBlogs.com" type="System.String"/>
            </param>
            <param name="encoder" parameterType="MSUnity9.IEncoder, MSUnity9" >
                <dependency name="encoder.null"/>
            </param>
        </constructor>
    </typeConfig>
</type>

And the results of running the app now:

to: steve

from: Mike@AardvarkBlogs.com

unity is great!

And thats our first look at constructor injection… we will revisit constructor injection again in later posts, however the next part will look at setter injection.

How to do this in Castle Windsor?

Responses

  1. […] 2008 Constructor Injection Unity Tutorial Added Posted by Michael under Uncategorized   9. Constructor Injection […]


Leave a comment