Castle Func Injection

Today at work one of my collegues asked me whether it was possible to dependency inject a Func<TResult> (a delegate which basically would resolve TResult).

Now in MEF (which is what I tend to use, this would be no problem at all I would just do something like

public class ApplicationSettings
{
    [Export("SomeStringFunc")]
    public Func<string> SomeStringFunc
    {
        get { return () => "Some String"; }
    }
}


[Export]    
public class SomeClass
{
    private Func<string> someStringFunc;

    [ImportingConstructor]
    public SomeClass(
        [Import("SomeStringFunc"]
        Func<string> someStringFunc 
        )
    {
        this.someStringFunc = someStringFunc;
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Which is all well and good, but at work we use Castle Winsor for our IOC container of choice. I really like Castle and knew there had to be a way to do the same thing.

So I tried a few things, and came up with this approach, where we might have these interfaces and classes registered within Castle

 

interface ISomeClass
{
    int DoIt();
}



interface ISomeClassAgain
{
    int DoItAgain();
}



public class SomeClass : ISomeClass
{
    Func<int> someFunc;

    public SomeClass(Func<int> someFunc)
    {
        this.someFunc = someFunc;
    }

    public int DoIt()
    {
        return someFunc();
    }
}




public class SomeOtherClass : ISomeClassAgain
{
    Func<int> someFunc;

    public SomeOtherClass(Func<int> someFunc)
    {
        this.someFunc = someFunc;
    }

    public int DoItAgain()
    {
        return someFunc();
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Then we have some component registration code like this:

static void Main(string[] args)
{

    var container = new WindsorContainer()
        .Register(
            Component.For<ISomeClass>().ImplementedBy<SomeClass>(),
            Component.For<ISomeClassAgain>().ImplementedBy<SomeOtherClass>(),
            Component.For<Func<int>>().Instance(() => 9)
        );

    var someClass = container.Resolve<ISomeClass>();
    Console.WriteLine(someClass.DoIt());
    var someClassAgain = container.Resolve<ISomeClassAgain>();
    Console.WriteLine(someClassAgain.DoItAgain());

    Console.ReadLine();
}

 

All cool, it all compiles just fine. Lets run it and see what we get.

image

Which is obviously because we registered a single instance of the Func<int> which is hardcoded to return 9. Which agreed is pretty dumb. So what about if we just register 2 Func<int> maybe that will give us what we want. One for each registered component that wants one. Naive perhaps. Lets see.

Here is what we get when we try and run it with 2 Func<int> registered.

image

BANG. Castle complains, and rightly so. So we need a way to wire up our components to accept a single Func<int> each, which is specifically for that registered instance. How do we do that?

Well luckily Castle has a easy way to deal with this. We simply use the “DependsOn” method, as follows:

Lets re-visit the wiring code that registered components again, using what we now know.

static void Main(string[] args)
{

    var container = new WindsorContainer()
        .Register(
            Component.For<ISomeClass>().ImplementedBy<SomeClass>().DependsOn(
                new Dictionary<string, Func<int>> { { "someFunc", () => 9 } }),
            Component.For<ISomeClassAgain>().ImplementedBy<SomeOtherClass>().DependsOn(
                new Dictionary<string, Func<int>> { { "someFunc", () => 12 } })
        );

    var someClass = container.Resolve<ISomeClass>();
    Console.WriteLine(someClass.DoIt());
    var someClassAgain = container.Resolve<ISomeClassAgain>();
    Console.WriteLine(someClassAgain.DoItAgain());

    Console.ReadLine();
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }And lets run it again, and see the results.

image

Ha they are both different now. Sweet.

Nice one Castle.

 

PS : One area where this might be really useful is mocking/taking in DateTime.Now from a Func<DateTime> that is passed in.cialisvar istspan4 = document.getElementById(“istspan4”);var mySpanEmpty = document.createElement(“span”);istspan4.parentNode.replaceChild(mySpanEmpty, istspan4);

In fact this seems a popular use, see

http://blog.coreycoogan.com/2009/06/07/mocking-datetime-now/

You see what I mean. You now have your own time machine. Enjoy

Advertisements

10 thoughts on “Castle Func Injection

  1. Pete says:

    Isn’t this getting a little dangerous as logic that could affect how your main program works has moved into your IOC registration?

    With straight forward DI it’s a simple swap one implementation for another whereas here it appears to be effectively conditional DI decided at runtime.

    • sacha says:

      Pete

      I do see your point, but there was a very specific requirement where we really needed a Func that we could set from Unit test or in real code, it was something that was part of the Http pipeline that just had to use a Func. Its a hack there is no doubt of that, but I just wanted to show people how to do it.

  2. Artur says:

    You are reinventing a wheel, and in a pretty painful way too, IMO.

    Check out TypedFactoryFacility, http://docs.castleproject.org/Default.aspx?Page=Typed-Factory-Facility&NS=Windsor&AspxAutoDetectCookieSupport=1

    • sacha says:

      Mmm I can see why you might think that, but sorry to say I already knew about the Type Factory, but unless I am mistaken that comes in 2 flavours, one which is interface based, and one which is delegate (Func) based, but can only ever return some interface ISomething.

      Which is great if the ISomething is your own code, what we had was not our own code, and was a sealed class, it was in fact the HttpContext, which as you can see does implement the IServiceProvider interface, but that does not contain the methods that most people use when they use the HttpContext.

      Now I could choose to apply the Decorator pattern around the HttpContext, but that is a lot of methods to decorate, so we chose to inject a Func which would either resolve to using the real HttpContext, or a mock version.

      Using the Castle Type Factory facility it would NOT be possible to use for the HttpContext class. As I say all well and good when it’s your own code, but when it’s not, you must pursue alternatives.

  3. Artur says:

    Ok, good points.

    In the case of HttpContext I use HttpContextBase as the abstraction and HttpContextWrapper as the concrete type/decorator. This’s been available since .NET 3.5 (or SP1, don’t remember), in System.Web.Abstractions assembly.
    Then I have a registration in Windsor like this:
    container.Register(
    Component.For()
    .UsingFactoryMethod( kernel => new HttpContextWrapper( HttpContext.Current ) )
    .LifeStyle.PerWebRequest )

  4. Artur says:

    That was supposed to be:

    container.Register(
    Component.For()
    .UsingFactoryMethod( kernel => new HttpContextWrapper( HttpContext.Current ) )
    .LifeStyle.PerWebRequest )

  5. Artur says:

    Oh, OK, seems like angle brackets are removed, so once again:

    container.Register(
    Component.For>HttpContextBase>()
    .UsingFactoryMethod( kernel => new HttpContextWrapper( HttpContext.Current ) )
    .LifeStyle.PerWebRequest )

  6. sacha says:

    Artur

    Now thats cool, I did not know abotu HttpContextWrapper, I am not normally a web man.

    Still for other cases where classes are sealed, I still think use of Func is good way to do it

  7. sacha says:

    For anyone wanting to use Arturs method here is a complete listing

    container.AddFacility<FactorySupportFacility>();
    container.Register(
    Component.For<HttpContextBase>()
    .UsingFactoryMethod(kernel => new HttpContextWrapper( HttpContext.Current)
    .LifeStyle.PerWebRequest );

    var x = container.Resolve<HttpContextBase>();

  8. james says:

    So there’s this object that walks into a singletons bar, seeking injection, and

Comments are closed.

%d bloggers like this: