How deep must I go in the classes to properly wire up Castle Windsor for DI?
Right, so I'm new to Castle and I'm trying to figure out how far I need to go to wire up a service. Below is a sample of the classes I'm working with and where they sit in the world I've created.
What I'm trying to accomplish it to properly wire up Castle so that I can call the TemplateEmailViaSalesforce class to do the work, and have the dependent classes wired up via DI from Castle. But I'm unsure of how far I have to go when registering components. Below is my first attempt (I'm registering via code as a trial, and this is a mashup of a couple methods to create the container)
IWindsorContainer container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
// add the DAL mapper factory
container.AddComponent<ITemplateMapperFactory>();
// individual mappers
container.Register(Component.For<ICSGEmailTemplateMapper>().UsingFactory((ITemplateMapperFactory f) => f.CSGEMailTemplate));
container.Register(Component.For<IUserMapper>().UsingFactory((ITemplateMapperFactory f) => f.User));
container.Register(Component.For<IGoupMapper>().UsingFactory((ITemplateMapperFactory f) => f.Group));
container.Register(Component.For<IAccountTeamMapper>().UsingFactory((ITemplateMapperFactory f) => f.AccountTeam));
container.Register(Component.For<ISalesTeamMapper>().UsingFactory((ITemplateMapperFactory f) 开发者_运维技巧=> f.SalesTeam));
container.Register(Component.For<ICSGFormulaMapper>().UsingFactory((ITemplateMapperFactory f) => f.CSGFormula));
container.Register(Component.For<ISFObjectDefinitionMapper>().UsingFactory((ITemplateMapperFactory f) => f.SFDCObjectDefinition));
container.Register(Component.For<ISFObjectValueMapper>().UsingFactory((ITemplateMapperFactory f) => f.SFDCObjectValue));
container.Register(Component.For<ISalesforceTemplateMapper>().UsingFactory((ITemplateMapperFactory f) => f.Template));
container.Register(Component.For<IRecipientMapper>().UsingFactory((ITemplateMapperFactory f) => f.Recipient));
// BLL stuff (domain components)...general
container.AddComponent<CSGEmailTemplateRepository, CSGEmailTemplateRepository>();
container.AddComponent<RecipientRepository, RecipientRepository>();
container.AddComponent<SFObjectDefinitionRepository, SFObjectDefinitionRepository>();
container.AddComponent<SFObjectValueRepository, SFObjectValueRepository>();
container.AddComponent<TemplateRepository, TemplateRepository>();
container.AddComponent<UserRepository, UserRepository>();
container.AddComponent<ITemplateService, TemplateService>();
// specific for this action
container.AddComponent<TemplateEmailerViaSalesforce>();
container.AddComponent<TemplateParse>();
// Aspects
container.AddComponent<TraceAspect>();
Now, I get an error later at: container.Resolve<TemplateEmailerViaSalesforce>();
AssemblerTests.ShouldCreateTemplateService : FailedTest method Tests.AssemblerTests.ShouldCreateTemplateService threw exception: Castle.MicroKernel.Facilities.FacilityException: You have specified a factory ('Castle.MicroKernel.Registration.GenericFactory`1[[CSG.Salesforce.TemplateEmailer.DAL.Access.IUserMapper, CSG.Salesforce.TemplateEmailer.DAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' - method to be called: Create) for the component 'CSG.Salesforce.TemplateEmailer.DAL.Access.IUserMapper' CSG.Salesforce.TemplateEmailer.DAL.Access.IUserMapper that failed during invoke. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Castle.MicroKernel.ComponentRegistrationException: Type CSG.Salesforce.TemplateEmailer.DAL.ITemplateMapperFactory is abstract.
The failure seems to be with IUserMapper which is defined as class UserMapper:BaseSalesforceMapper<UserData>,IUserMapper
The other mappers work but I get an error that not all dependencies were satisfied, which I need the IUserMapper registration to satisfy fully.
How far down the rabbit hole do I have to go to get this wired? At this point I'm looking though the BLL into the DAL and into a base class that app mappers are built from and it doesn't seem right. I'm struggling with figuring out what I have to get registered and what will be implicitly done with DI by Castle itself.
Any help at all would be appreciated. Thanks.enter code here
These are the issues I see in your code:
container.AddComponent<ITemplateMapperFactory>();
you need to provide the implementation class here, this is the reason you're getting that exception when resolving.
container.AddComponent<UserRepository, UserRepository>();
If you're registering a component without an interface there's no need to repeat the implementation type as service type.
UsingFactory()
is obsolete. UseUsingFactoryMethod()
instead.AddComponent()
is obsolete. UseRegister(Component.For...))
instead.- In the latest version of Windsor there's no need to add the FactorySupportFacility to use
UsingFactoryMethod()
.
what I have to get registered and what will be implicitly done with DI by Castle itself.
You need to register every component that you want Windsor to manage. If you don't register it, Windsor doesn't know about it. You can set up conventions to avoid registering components individually though. What Windsor does for you is auto-wire components implicitly.
I don't completely understand everything that you are doing here. It might be better to start simply, with just a few classes, and take baby steps to getting everything configured the way you want. You also might want to look at auto-wiring for Windsor--it should make at least some of your components easier to configure.
All that said, it looks to me like you are specifying an interface to use for your factory implementation (ITemplateMapperFactory). As the error message shows: "ITemplateMapperFactory is abstract". Windsor can't instantiate something that can't be instantiated.
Disclaimer: I'm not an expert on the factory facility, as I don't use it.
精彩评论