Jeremy Frey Jeremy Frey - 17 days ago 4
C# Question

Castle Windsor: How do I register a factory method, when the underlying type isn't accessible to my assembly?

I have a project where my business layer is constructed using DI, but I'm trying to go an additional step and use Windsor to manage object construction.

Let's just say I have a pre-existing data layer (that I don't want to modify), that can be accessed via the following interface:

interface IDataFactory {
IDataService Service { get; }
}


A series of classes in my business layer depend on the services exposed through IDataFactory:

IFactory factory = DataFactory.NewFactory();
IBusinessService service = new ConcreteBusinessService(factory.Service);


I understand that in order to register IBusinessService to the Castle Windsor container, I'd use code similar to this:

IWindsorContainer container = new WindsorContainer();
container.AddComponent("businessService", typeof(IBusinessService), typeof(ConcreteBusinessService));


But for the life of me, I can't figure out how to register services from my data layer, using the my existing factory object. In essence, I'd like to say:

container.AddComponent("dataService", typeof(IDataService), factory.service);


Windsor seems to want me to say container.AddComponent("dataService", typeof(IDataService), typeOf(SomeConcreteDataService)), but in this instance, ConcreteDataService is internal to that assembly, and thus not accessible in mine.

How would I go about wiring up the data service, given that SomeConcreteDataService isn't known to my assembly?




This question is very similar to my own, except in my case, the AddComponent("calculator", typeof(ICalcService), typeof(CalculatorService), "Create"); call wouldn't work -- CalculatorService would be internal to another assembly, not available to the assembly wiring up the container.

Answer

Using Windsor 2.0:

[TestFixture]
public class WindsorTests {
    public interface IDataService {}

    public class DataService: IDataService {}

    public interface IDataFactory {
        IDataService Service { get; }
    }

    public class DataFactory: IDataFactory {
        public IDataService Service {
            get { return new DataService(); }
        }
    }

    [Test]
    public void FactoryTest() {
        var container = new WindsorContainer();
        container.AddFacility<FactorySupportFacility>();
        container.AddComponent<IDataFactory, DataFactory>();
        container.Register(Component.For<IDataService>().UsingFactory((IDataFactory f) => f.Service));
        var service = container.Resolve<IDataService>();
        Assert.IsInstanceOfType(typeof(DataService), service);
    }
}

See the fluent API wiki page for more information.