New Castle Windsor feature – typed arguments

With Wind­sor 2.1.1 out the door, we’re already work­ing on ver­sion 3.0 (and look­ing for your feed­back and ideas for the next ver­sion!). Yes­ter­day I com­mit­ted first “big” fea­ture that prob­a­bly will make it to the release.

DISCLAIMER:

All the code shown here rep­re­sents a work in progress. Keep in mind that final ver­sion may be dif­fer­ent. This also means that any feed­back on this fea­ture is appreciated.

Named Argu­ments

In cur­rent ver­sion of Wind­sor you can define inline depen­den­cies for a com­po­nent in at least three dif­fer­ent ways:

  • When reg­is­ter­ing it (with value obtained at reg­is­tra­tion time):
    container.Register(

        Component.For<ICustomer>()

            .ImplementedBy<CustomerImpl>()

            .DependsOn(

                Property.ForKey("Name").Eq("Caption Hook"),

                Property.ForKey("Address").Eq("Fairyland"),

                Property.ForKey("Age").Eq(45)

                )

            );

  • When reg­is­ter­ing it (with value obtained at res­o­lu­tion time), AKADynamic Para­me­ters
    container.Register(

        Component.For<ClassWithArguments>()

            .LifeStyle.Transient

            .DynamicParameters((k, d) =>

            {

                d["timeStamp"] = DateTime.Now;

                d["user"] = Thread.CurrentPrincipal.Identity;

            })

        );

  • When resolv­ing it (although this is some­thing you should strive to avoid, using con­struc­tor injec­tion and/or Typed fac­tory facil­ity)
  • var component = container.Resolve<ClassWithArguments>(new

    {

        TimeStamp = DateTime.Now,

        User = Thread.CurrentPrincipal.Identity

    });

What all these approaches have in com­mon is that you spec­ify depen­dency by name. Wind­sor when resolv­ing the com­po­nent will then use the value you pro­vided for con­struc­tor argu­ments or set­table prop­er­ties with that name it finds on the com­po­nent. What if you don’t care about the name?

Typed Argu­ments

Trunk ver­sion of Wind­sor lets you do just that – omit the name in which case Wind­sor will use the type of the argu­ment as the sole infor­ma­tion when build­ing your component.

container.Register(

       Component.For<ClassWithArguments>()

           .Lifestyle.Transient

           .DependsOn(

              Property.ForKey<DateTime>().Eq(DateTime.Now),

              Property.ForKey<IIdentity>().Eq(Thread.CurrentPrincipal.Identity))

    );

As you can see here we use the type as the key for the depen­dency. This works also with dynamic para­me­ters as well as when pass­ing argu­ments straight from the call site. A new class – Argu­ments has been intro­duced to accom­mo­date this new fea­ture (although ordi­nal Hashtable or Dictionary<object,object> will do just fine as well) .

container.Resolve<ClassWithArguments>(

    new Arguments(new object[]

    {

        DateTime.Now,

        Thread.CurrentPrincipal.Identity

    })

);

The Argu­ments class itself imple­ments IDic­tionary and can wrap either another IDic­tionary con­tain­ing either named or typed argu­ments, anony­mous type con­tain­ing named argu­ments or array of objects to be used as typed argu­ments. It is advised to use this type when you plan to use typed arguments.

Addi­tion­ally to help you deal with fill­ing the dic­tio­nar­ies in more usable fash­ion an exten­sion method on IDic­tionary (so they work for Argu­ments type as well) called Insert (with few over­loads) has been intro­duced. It lets you insert argu­ments in a flu­ent, more user friendly fashion.

container.Register(

    Component.For<ClassWithArguments>()

    .DynamicParameters((k, d) =>

        d.Insert(DateTime.Now)

        .Insert(Thread.CurrentPrincipal.Identity))

    );

Final words

While this may be appeal­ing at first to use typed argu­ments every­where, resist the temp­ta­tion unless you have a good rea­son. Named argu­ments should always be your first choice. Name is a valu­able con­tex­tual infor­ma­tion that may improve the read­abil­ity of your code. Wind­sor will favor named argu­ments over typed and use the lat­ter only if it can’t find a match­ing named argument.

  • http://thesoftwaresimpleton.blogspot.com/ Paul Cowan

    Do you think this is a good idea to have all these dif­fer­ent ver­sions of wind­sor released so quickly together with­out any clear guid­ance of what the upgrade path is?

    I am hav­ing seri­ous doubts about using cas­tle any­more because of the depen­dency mess it seems to pro­duce in any project that uses it.

    You guys can keep on slap­ping out dif­fer­ent ver­sions but what if I have a project that depends on cas­tle 2.1.1 and then use another bit of OSS that is built on the lat­est ver­sion of wind­sor or a pre­vi­ous version?

    I have to some­how rebuild all the castle.core etc. to the lat­est versions.

    Then I have to get Nhiber­nate which is built against a dif­fer­ent ver­sion of cas­tle altogether.

    Do you guys have no ideas about how to make this more managable??