Resolving generics with Castle Windsor in WCF

169 views Asked by At

I've spent a little time coming to the following design and would appreciate some feedback - I'm using Windsor to property inject a type for use by a Wcf service.

My Interface initially looked like this where the response and request types are abstract:

public interface IFooHandler
{
    CheckFooResponse CheckFoo(CheckFooRequest request);
}

I was concerned that I wouldn't be able to control which implementations of the abstract classes were used in classes implementing IFooHandler so the design changed to:

SO Question 1

public interface ICheckFooHandler<TRequest, TResponse> 
    where TRequest : CheckFooRequest where TResponse : CheckFooResponse
{
    TResponse CheckFoo(TRequest request);
}

and usage:

public class CheckFooHandler : ICheckFooHandler<MyFooRequest, MyFooResponse>
{
    MyFooResponse CheckFoo(MyFooRequest request) { ... }
}

I then tried to wire up Windsor:

IoCContainer = new WindsorContainer();

IoCContainer.Register
(Component
.For(typeof(ICheckFooHandler<,>))
.ImplementedBy(typeof(CheckFooHandler<,>)));

which I couldn't get to work until I changed the implementation of CheckFooHandler to:

SO Question 2

public class CheckFooHandler<TRequest, TResponse> :  ICheckFooHandler<TRequest, TResponse>
    where TRequest : MyCheckFooRequest 
    where TResponse : MyCheckFooResponse, new()
{
    public TResponse CheckFoo(TRequest request)
    {
        ...
        var response = new TResponse();
        response.MyResponseProperty = "baz";
    }

which fulfils the generic interface contract while allowing Windsor's generic syntax to work.

In my Wcf Service, I have the following private property, injected by Windsor:

private ICheckFooHandler<MyCheckFooRequest, MyCheckFooResponse> _checkFooHandler;

private ICheckFooHandler<MyCheckFooRequest, MyCheckFooResponse> CheckFooHandler
{
    get
    {
        if (_checkFooHandler == null)
        {
            _checkFooHandler = Global.IoCContainer
                .Resolve<ICheckFooHandler<MyFooRequest, MyFooResponse>>();
        }
    }
}

This design get me compile time safety in the handler and allows me to utilise IoC as per the previous questions.

My main issue is having to use the concrete MyFoo types rather than the abstract ones in the Resolve<>(), Property & field signatures. I was hoping to be able to specify the concrete type once and let Windsor do the rest.

Lastly I've never used the new() generic constraint, is my usage valid in concrete CheckFoo()?

1

There are 1 answers

0
Vladimir Moushkov On

You don't provide information how your Wcf service is being setup so assume you are not using Castle Windsor.

You can fully setup your application runtime and it Wcf service by Castle Windsor container using the Wcf Facility.

Example:

    container.AddFacility<WcfFacility>();

    foreach (var wcfType in types.Where(t => t.IsInterface == false && t.IsAbstract == false)) // types should be coming from AppDomain.Current assemblies
    {
        foreach (var anInterface in wcfType.GetInterfaces().Where(anInterface => anInterface
            .GetCustomAttributes(typeof(ServiceContractAttribute), true).Any()))
        {
            var serviceModel = new DefaultServiceModel().Hosted();

            container.Register(Component.For(anInterface)
                                        .ImplementedBy(wcfType)
                                        .AsWcfService(serviceModel)
                    );
        }
    }

It will register WCF services available. Then you should be able to rely on your typed dependencies directly in your WCF Service's constructor.