BenWillkommen
BenWillkommen

Reputation: 1472

What control do I have over the TypedFactory Windsor implements?

My colleague set up a Windsor TypedFactoryFacility in our project.

I'm new to Windsor and don't understand how it is implementing the the methods in the IServiceFactory interface we register as a factory. When I saw a Create method that takes a type parameter T and returns a T, I figured that it's probably calling the container's Resolve method under the covers.

I need an overload of Create that takes a Type as a parameter and returns an object. Since the container's Resolve method has both of these flavors:

T Resolve<T>(string key);
object Resolve(Type service);

I thought adding the overload of Create would work. Instead, it appears to be trying to resolve a System.Object instead of the Type I pass in.

Is there a way to make Windsor implement my Create method the way I want it to? I've poked around a bit with reflector, but can't figure it out.

Here is the registration:

container.AddFacility<TypedFactoryFacility>();
        container.Register(
                Component.For<IServiceFactory>()
                        .AsFactory()
                        .LifeStyle.Transient);

and the interface itself:

public interface IServiceFactory
{
    //Original Create method that works
    T Create<T>();

    //The overload that I need that throws an exception
    object Create(Type service)

    void Release(object service);
}

Upvotes: 0

Views: 823

Answers (1)

Do you want to call something like serviceFactory.Create(typeof(IMyServce)) instead of serviceFactory.Create<IMyService>()?

Try using reflection in an extension method, like this

public static class ServiceFactoryExtensions
{
    public static object Create(this IServiceFactory factory, Type serviceType)
    {
        return typeof(IServiceFactory).GetMethod("Create")
            .MakeGenericMethod(serviceType).Invoke(factory, new object[]{});
    }
}

EDIT:

This extension method does indeed work with a factory created by Castle Windsor.

Here's my original test code, which you can drop into Program.cs of a VS2010 console application, add a reference to Castle.Core and Castle.Windsor, and run. I used Castle.Windsor 2.5.4.

using System;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace StackOverflow9198461
{
    public static class ServiceFactoryExtensions
    {
        public static object Create(this IServiceFactory factory, Type serviceType)
        {
            return typeof(IServiceFactory).GetMethod("Create")
                .MakeGenericMethod(serviceType)
                .Invoke(factory, new object[] { });
        }
    }

    class Program
    {
        static void Main()
        {
            var container = new WindsorContainer();
            container.AddFacility<TypedFactoryFacility>();
            container.Register(Component
                .For<IServiceFactory>()
                .AsFactory());
            container.Register(Component
                .For<IMyService>()
                .ImplementedBy<MyService>()
                .LifeStyle.Singleton);
            var factory = container.Resolve<IServiceFactory>();
            var s1 = factory.Create<IMyService>();
            var s2 = factory.Create(typeof(IMyService));
            Console.WriteLine(s1.GetType().FullName);
            Console.WriteLine(s2.GetType().FullName);
            if (s1 == s2) Console.WriteLine("Success");
        }
    }

    public interface IServiceFactory
    {
        //Original Create method that works
        T Create<T>();

        ////The overload that I need that throws an exception
        //object Create(Type service)

        void Release(object service);
    }

    public class MyService : IMyService
    {
    }

    public interface IMyService
    {
    }
}

Upvotes: 0

Related Questions