Saturday, September 06, 2008
As a brief follow up to my last post here I thought I'd quickly post about something I've been doing lately with my own windsor configurations, which is pretty minor - but saves me a little grief when it comes to refactoring etc.

Basically I have this extension method:


public static ComponentRegistration<S> RegisterTransient<S>(this IWindsorContainer container, ComponentRegistration<S> registration)

{

  container.Register(registration.LifeStyle.Transient);

  return registration;

}



Which then lets me do this:


var serviceA = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryA>());


var serviceB = container.RegisterTransient(Component.For<IStaffRepository>()

  .ImplementedBy<StaffRepositoryB>());

 

container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

  .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq(serviceB.Name, serviceA.Name)));

 

var staffService = (StaffService)container.Resolve<IStaffService>();

 

Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);



notice the lack of strings when registering service overrides... it's a minor thing, but I find it quite handy... plus it generally makes it easier to identify the lifestyle of the components being registered because it's a little more in your face, i.e. your making an explicit decision... though anywhere that lifestyle poses a risk you should obviously be writing some unit tests to verify your getting the expected behavior when resolving that service anyway.

Also, while looking at ComponentRegistration<S> -the other nice thing about the fluent component registration is it works quite well for add-ons that introduce their own services which aren't loaded into a seperate app domain or child kernel ...

Just give the add-in an installation "helper" which only exposes a method taking a ComponentRegistration<S> for registering the component... you can then defer when those services are actually registered in the kernel, and can use the names of the components or other info to unregister them if the add-in is turned off (obviously this is a rainy day scenario and there are problems with this approach, but so far I've found it to work quite well).

posted @ Friday, September 05, 2008 9:13:02 PM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
If you recall when configuring the container via xml you can do a service override like so:

<configuration>

 

    <components>

        <component id="smtp.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SmtpMailSender, AssemblyName" />

 

        <component id="sendmail.sender"

            service="Namespace.IEmailSender, AssemblyName"

            type="Namespace.SendMailEmailSender, AssemblyName" />

 

        <component id="newsletter"

            type="Namespace.NewsLetterSenderService, AssemblyName">

 

            <parameters>

                <sender>${smtp.sender}</sender>

            </parameters>

 

        </components>

 

    </components>

 

</configuration>


Check out the documentation on the castle site for some more details.

I recently got an email question around how to do this with the fluent interface - unfortunately with the XML, Binsor and Fluent interfaces all being used for registering and configuring the MicroKernel/Windsor Container the documentation is a little patchy across all three (with XML of course having the best coverage) - so here's an example of service override for the fluent interface.

First off the various services we'll be wiring up in this example.

public interface IStaffService

{

}

 

public class StaffService : IStaffService

{

  public IStaffRepository Repository { get; set; }

}

 

public interface IStaffRepository

{

}

 

public class StaffRepositoryA : IStaffRepository

{

}

 

public class StaffRepositoryB : IStaffRepository

{

}


And now the actual tests..

public class ServiceOverrideTests

{

  private WindsorContainer container;

 

  public ServiceOverrideTests()

  {

    container = new WindsorContainer();     

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.a").ImplementedBy<StaffRepositoryA>().LifeStyle.Transient);

    container.Register(Component.For<IStaffRepository>().Named("repository.staff.b").ImplementedBy<StaffRepositoryB>().LifeStyle.Transient);

  }

 

  [Fact]

  public void ByDefaultStaffServiceWiredUpToFirstServiceRegistered()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>().LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryA>(staffService.Repository);     

  }   

 

  [Fact]

  public void WithServiceOverrideCanPickImplmentationByKey()

  {

    container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                        .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")).LifeStyle.Transient);

 

    var staffService = (StaffService)container.Resolve<IStaffService>();

 

    Assert.IsType<StaffRepositoryB>(staffService.Repository); 

  }

}


With .ServiceOverrides(ServiceOverride.ForKey("Repository").Eq("repository.staff.b")) being the code we're interested in... obviously if it was a constructor override we'd be using the name of the parameter in the constructor.

The Eq method can also take of an array of strings... which, you guessed it, means we can handle arrays of services as well ... which can be quite handy if order is important to some kind of service you're building where there are multiple contributors or some form of pipeline, lets take a look at that:

public class StaffService : IStaffService

{

  public IStaffRepository[] Repositories { get; set; } // <- is now an array of staff repository...

}


And the associated test - notice we just pass in a list of the service names...

[Fact]

public void WithServiceOverrideCanPickImplmentationByKey()

{

  container.Register(Component.For<IStaffService>().Named("service.staff").ImplementedBy<StaffService>()

                      .ServiceOverrides(ServiceOverride.ForKey("Repositories").Eq("repository.staff.b", "repository.staff.a")).LifeStyle.Transient);

 

  var staffService = (StaffService)container.Resolve<IStaffService>();

 

  Assert.IsType<StaffRepositoryB>(staffService.Repositories[0]);

  Assert.IsType<StaffRepositoryA>(staffService.Repositories[1]);

}


Hopefully this proves useful to Jason (who sent me the email) and anyone else who's getting started with windsor and strugling a little to setup their container.
posted @ Friday, September 05, 2008 8:29:15 PM (New Zealand Standard Time, UTC+12:00)    Comments [4] | Trackback |
 Tuesday, September 02, 2008
So I received a question recently via email from someone following the container tutorials, which read like so:

Read through you tutorials and great work!

Have a question for you though, that I can't seem to find an answer in google. On decorators. How do you provide state dependencies that are unknown at configuration time?

So I ask for an IRepository and I have configuration setup to wrap it in a IValidator and maybe an ISecurity. However, ISecurity has a dependency on a runtime determined role (say from multiple sources, possibly including a state value on IWidget) and the user id (for argument sake isn't available on the context).

I want to call T Get() on IRepository. How do you get it all setup?

Many Thanks!

As I see it there were two distinct questions asked:
  • How to wire up generic decorator chains (though I suspect they already know how to do that).
  • How to pass in parameters/dependencies at run time.
So Let's look at doing these two things, I'm going to steer clear of xml configuration because that's so 2 years ago ;o)

First off let's create the repository interface:

public interface IRepository<T>

    where T : class, new()

{

    T Get(int id);

}


Then the root implementation (we can't keep chaining forever, at some point we have to hit an implementation which can actually return the results we want).

public class StubRepository<T> : IRepository<T>

    where T : class, new()

{

    public T Get(int id)

    {

        return new T();

    }

}


And finally a decorator for "security"...

public class SecurityDecorator<T> : IRepository<T>

    where T : class, new()

{

    private readonly IRepository<T> _inner;

 

    public SecurityDecorator(IRepository<T> inner)

    {

        _inner = inner;

    }

 

    public T Get(int id)

    {

        return _inner.Get(id);

    }

}


better have a widget too... for good measure:

public class Widget

{

}


At this point we can write a test - I'm an xUnit fanboy these days (typing less == good) so let's take a look:

public class ContainerTests

{

    private readonly IWindsorContainer container;

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

}


Notice we register the components in top to bottom order i.e. decorators first, followed by the underlying implementation, for something as simple as this you don't really need to use the fluent interface for registering components - but I find it's good to be consistent.

Now, the second question is about injecting "context" - this is really just another way of saying "some of my dependencies can't be known until just before I attempt to resolve the service" ... no problem... so let's make some modifications:

First off I'm going to make a user...

public interface IUser

{

}


Next thing I'm going to do is add a User property to my security context (ugh, this seems like a better job for some kind of "ICurrentUserHolder" service, but that's beside the point).

public class SecurityDecorator<T> : IRepository<T>

    where T : class, new()

{

    private readonly IRepository<T> _inner;

 

    public SecurityDecorator(IRepository<T> inner)

    {

        _inner = inner;

    }

 

    public T Get(int id)

    {

        return _inner.Get(id);

    }

 

    public IUser User { get; set; } // <-- the current user

}


Now let's add another test to ensure everything is being injected properly...

public class ContainerTests

{

    private readonly IWindsorContainer container;

    private readonly IUser user = MockRepository.GenerateStub<IUser>();

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));           

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

 

    [Fact]

    public void GetRepository_ForWidget_WhenSupplyingUserInjectsUserIntoSecurityRepository()

    {

        var securityDecoratorForWidget = (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user});

        Assert.Same(user, securityDecoratorForWidget.User);

    }

}


Notice the additional argument of an anonymous class being passed to Resolve, this allows us to provide additional parameter dependencies (in this case a stub user is being supplied).

Finally what about passing in some roles... this is much of the same, but I'll include it for completeness... so we add a role interface:

public interface IRole

{

    bool IsMember(IUser user);

}


Then we'll add a collection of roles to the decorator and provide a rather primitive check against the roles when attempting to get a widget instance:

    public class SecurityDecorator<T> : IRepository<T>

        where T : class, new()

    {

        private readonly IRepository<T> _inner;

 

        public SecurityDecorator(IRepository<T> inner)

        {

            _inner = inner;

        }

 

        public T Get(int id)

        {

            CheckPermission();

            return _inner.Get(id);

        }

 

        public IUser User { get; set; }

 

        public IList<IRole> Roles { get; set; } // <-- the roles to check

 

        private void CheckPermission()

        {

            if (User == null || Roles == null) return;

 

            if (Roles.Any(role => !role.IsMember(User)))

            {

                throw new Exception("You do not have permission");

            }

        }

    }


And finally we update our test with checks for both passing and failing on the permissions check.

public class ContainerTests

{

    private readonly IWindsorContainer container;

    private readonly IUser user = MockRepository.GenerateStub<IUser>();

    private readonly IRole failingRole = MockRepository.GenerateStub<IRole>();

    private readonly IRole passingRole = MockRepository.GenerateStub<IRole>();

 

    public ContainerTests()

    {

        container = new WindsorContainer();

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (SecurityDecorator<>)));

        container.Register(Component.For(typeof (IRepository<>)).ImplementedBy(typeof (StubRepository<>)));

        passingRole.Stub(stub => stub.IsMember(user)).Return(true);

    }

 

    [Fact]

    public void GetRepository_ForWidget_ReturnsSecurityDecoratorOfTypeWidget()

    {

        var widgetRepository = container.Resolve<IRepository<Widget>>();

        Assert.True(widgetRepository is SecurityDecorator<Widget>);

    }

 

    [Fact]

    public void GetRepository_ForWidget_WhenSupplyingUserInjectsUserIntoSecurityRepository()

    {

        var securityDecoratorForWidget = (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user});

        Assert.Same(user, securityDecoratorForWidget.User);

    }

 

    [Fact]

    public void Get_ForWidgetWhenUserMatchesAllRoles_ReturnsWidget()

    {

        var securityDecoratorForWidget =

            (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user, Roles = new List<IRole> {passingRole}});

         Assert.NotNull(securityDecoratorForWidget.Get(1));

    }

 

    [Fact]

    public void Get_ForWidgetWhenUserDoesNotMatchAllRoles_ThrowsException()

    {

        var securityDecoratorForWidget =

            (SecurityDecorator<Widget>) container.Resolve<IRepository<Widget>>(new {User = user, Roles = new List<IRole> {passingRole, failingRole}});

         var exception = Assert.Throws<Exception>(() => securityDecoratorForWidget.Get(1));

        Assert.Equal("You do not have permission", exception.Message);

    }

}


And that's it... could not be simpler.


posted @ Tuesday, September 02, 2008 5:11:06 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
Hi All,

I'm afraid I'm going to have to postpone the Architecture chat until next week, due to other commitments on Thursday.

So it's now rescheduled for next Thursday - 11th September - if anyone has any topics, or saw anything cool at code camp or teched this week then leave a comment on this post and I'll add to the list of topics for next week.




posted @ Tuesday, September 02, 2008 3:45:13 AM (New Zealand Standard Time, UTC+12:00)    Comments [2] | Trackback |
 Wednesday, August 27, 2008
It's been a back and forth discussion on the OAuth list for a while now - and with some people (zealots? ;o) having ideas they weren't even willing to contribute to the OAuth group until the IPR was sorted I'm glad to finally see it's been completed, this should hopefully help to improve the longevity and adoption of the standard by some who have been fence sitting.

So what's happened?

Well all all parties involved in building the original spec have signed an agreement of non-assertion, so now OAuth can be safely implemented anywhere without concern about lawsuits related to the IP in the spec.

OAuth is a pretty elementary standard in it's version 1 state - so in some ways it was inevitable that this would happen (or at least I thought so) - there wasn't much to gain by any of the contributors blocking the progress of it becoming an open standard - but it's involved a lot of work to get it there by all accounts, so full credit goes to all involved!

For a detailed writeup check out the post from Eran Hammer-Lahav or the post on Read/write web.

Conspicuous by it's absence is Microsoft, but for no other reason than they did not contribute to the OAuth standard - and so didn't have to sign - but of course LiveId does tackle delegated authentication - so in some ways they have a competing platform for handling delegation, presumably because OAuth doesn't provide a rich enough set of features at this stage to handle some of the more complex scenarios around scalability, signing message bodies etc. - though I'm just hazarding a guess, LiveId was presented at the OAuth summit earlier this year.

 |  | 
posted @ Wednesday, August 27, 2008 1:24:58 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
 Tuesday, August 19, 2008
Only just catching up on my blog reading from the last week or so this evening - so only just came across this, but its pretty cool! - it's like deep zoom for power point - the project is pptPlex from the OfficeLabs team.

I wonder if anyone at teched / codecamp in New Zealand this year will be using it... I normally do a mind map when I'm structuring a presentation, proposal for a client/whatever - be great to actually present the mind map itself then zoom in to show the details...mmm

posted @ Tuesday, August 19, 2008 8:41:15 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
 Monday, August 18, 2008
Hi all, there's an Architecture chat this Thursday - 21st August @ 11:30am onwards.

Some things that I've caught my eye since last time:
  • .Net 3.5 SP1 and VS2008 RTM are here
  • VS2K8SP1 and SQL2K8 installs are a big mixed bag, some people no problem, other tearing hair out!
  • And so are the war stories such as regressions and critical changes - doh!
  • Visibility and trouble with non-developers being unable to quantify the quality of developer outputs - sparked off by this post by Casey.
  • Resharper 4.01 RC1 is out.
  • ASP.NET MVC now and in the future (i.e. where it's going, and perhaps a discussion on future of monorail vs. MVC and Monorail 2??).
  • Security practices on MVC, WCF etc.
  • Redmine - an interesting (and nicer) alternative to Trac - wonder if there's an easy transition path for existing Trac sites?
Edit: updated this list with some suggestions from others.

If anyone has any topic suggestions - just make a post on this entry, or send me an email / IM message.

Details of previous posts and directions etc. can be found here on the wiki.

posted @ Monday, August 18, 2008 10:47:10 AM (New Zealand Standard Time, UTC+12:00)    Comments [5] | Trackback |
Here's the write-up for Architecture Chat #32 (from Thursday 7th August 2008) ... some of the things we discussed:
  • Jabl / Jass  (Javascript abstraction language) - we discussed this approach of writing languages that transform into another language - the tradeoffs of debug experience vs. productivity etc.
  • Debug experiences in DSL's and in particular the lack of support in these language rewriting/transformation projects.
  • The magic bullet language i.e. two-way debugging experience, language independent refactoring support, modular/pluggable language support (sorta like Boo).
  • Code camp at the end of this month.
  • Self explaining code / blaming code (i.e. code that can explain the decisions it makes in english, or at least identify the blame (i.e. steps) that lead to the result it selected.  Though we didn't bring it up, I quite like the way Rhino Security does this.
  • xUnit thoughts after a month of using it on a commercial project.
  • Ice ZeroC - WCF alternative?
  • Sql Server partitioned tables, and the simpler query plans / improvements in 2008.
See the wiki for write up's of previous chats, thanks to all those who attended.

posted @ Monday, August 18, 2008 6:22:54 AM (New Zealand Standard Time, UTC+12:00)    Comments [4] | Trackback |
 Friday, August 15, 2008
Yesterday afternoon I presented a quick 20 minute presentation to the Enterprise Architect user group - it was an interesting opportunity to talk with both an Enterprise Architect lead developer and analysts/BA's etc. who are using Enterprise Architect on a daily basis - there's nothing quite like doing something and then even more so presenting on what you've done to really firm up some conclusions / ideas around it (and as is often the case with me, spark 20 ideas for new products I could build to make it better/smarter).

For anyone who's interested here's the slide deck I presented - and also some links to things that were discussed:
Thanks to catch for hosting the group and providing the video conferencing facilities to link Auckland / Wellington (small tip, if you are presenting to two groups be sure to sit at the end of the table looking towards the camera, or your spend your whole time ping-ponging your head towards one group and the other ;) - and also thanks to everyone who came along and listened.

Also of interest was the discussion after the presentation around providing a number of example/sample MDA transformations through Sparx Systems New Zealand site - which should mean that before the end of the year you will be seeing both guidance and examples on developing MDA transformations targeting NHibernate, NHibernate search, ActiveRecord, Monorail and RhinoSecurity starting to emerge (what I tend to loosely call the "Castle stack" for want of a better term.) - which I'll post about it as it starts to happen.

posted @ Friday, August 15, 2008 2:19:21 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
 Wednesday, August 06, 2008
There's a few things going on in Auckland over the next month or so, just to summarize if you haven't been paying attention :)
So plenty of things going on!

I would suggest signing up for the code camp sooner rather then later if you don't want to miss out - also if you know of any other events that I've left off this list, drop me a comment and I'll add them to it.

posted @ Wednesday, August 06, 2008 7:23:04 AM (New Zealand Standard Time, UTC+12:00)    Comments [0] | Trackback |
Search
FeedCount

Tags...
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation