سؤال

I have an API controller that fires a service that uses constructor dependency injection. I would like to use the Windsor container to inject those dependencies, but I'm not sure the best practice.

Here's part of the API controller factory:

private readonly IWindsorContainer _container;
private readonly ServiceFactory _serviceFactory;
...
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
    Arguments args = new Arguments(new { serviceFactory = _serviceFactory });
    IHttpController controller = (IHttpController)_container.Resolve(controllerType, args);
    request.RegisterForDispose(new Release(() => _container.Release(controller)));
    return controller;
}
...

Here's part of the Service Factory:

private readonly IWindsorContainer _container;
...
public IService Create(Type serviceType, ApiRequestModel apiRequest)
{
    Arguments args = new Arguments(new { request = apiRequest });
    return (IService)_container.Resolve(serviceType, args);
}
...

Here's part of the API controller:

private ServiceFactory _serviceFactory { get; set; }
...
public object Post([FromBody]ApiRequestModel request)
{
    ...
    Type serviceType = Assembly.Load("TestProject").GetType("TestClass");
    IService instance = _serviceFactory.Create(serviceType, request);
    ...
    _serviceFactory.Release(instance);
}
...

The Service Factory contains an instance of the Windsor container, so is it a bad idea to expose it to the API controller? If so, what is the best alternative? Thanks.

هل كانت مفيدة؟

المحلول

My solution was to use a generic typed factory facility (e.g. http://thesenilecoder.blogspot.com/2012/04/ioc-windsor-typedfactoryfacility-and.html)

The factory only consists of the following interface:

public interface IServiceFactory
{
    T Create<T>(ApiRequestModel request) where T : IService;

    void Release(IService service);
}

And here's how it gets installed to the container:

container.AddFacility<TypedFactoryFacility>();
container.Register(
    Component.For<IServiceFactory>().AsFactory(),
    Classes.FromThisAssembly().BasedOn<IService>().LifestylePerWebRequest());

That gets injected into the API controller and allows me to create generic types. I used reflection to resolve the generic type before I went to the factory.

Type serviceType = Assembly.Load("TestProject").GetType("TestClass");
MethodInfo factoryMethod = _serviceFactory.GetType().GetMethod("Create").MakeGenericMethod(serviceType);
IService instance = (IService)factoryMethod.Invoke(_serviceFactory, new object[] { request });
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top