2

I have the following code in my MVC application which works fine.

container.Register(Component.For<CountryServiceBase>()
    .ImplementedBy<CountryService>()
    .LifestylePerWebRequest());

Castle Windsor creates a component

CountryService / CountryServiceBase

My controller gets an instantiated object here :

public class MyController : MainController
{
    public CountryServiceBase CountryService {get; set;} // instantiate by Ioc : OK

My problem is that I have a lot of classes to register. So using Castle Windsor I did the following :

container.Register(
    Types
    .FromAssemblyNamed("mynamespace")
    .BasedOn(typeof(ServiceBase<>))
    .WithService.Base()
    .LifestylePerWebRequest());

Castle Windsor creates my components

CountryService / ServiceBase<Country>
CountryServiceBase / ServiceBase<Country>

But my MVC Application awaits a CountryService / CountryServiceBase and I don't know how to specify to Castle Windsor that it can match back CountryServiceBase to CountryService as both those classes (one of them being an abstract one) inherits ServiceBase

Is it even possible ?

Note : I posted a similar question but my investigation leads to a more accurate one so I deleted the old one.

AMS
  • 439
  • 2
  • 12
  • Try to change `public CountryServiceBase CountryService {get; set;}` by `public ServiceBase CountryService {get; set;}` – Hamlet Hakobyan Jun 12 '15 at 15:14
  • It would work but in abstract class CountryServiceBase, I have several declared methods. Otherwise it would work. – AMS Jun 12 '15 at 15:18
  • Maybe `BasedOn(typeof(CountryServiceBase))`? – Hamlet Hakobyan Jun 12 '15 at 15:22
  • Doing so I would have to manually register all my classes and my goal is to avoid such a thing. Thanks anyway – AMS Jun 12 '15 at 15:29
  • `WithService.AllInterfaces()`? – Phil Degenhardt Jun 15 '15 at 02:54
  • @PhilDegenhardt : I tried but It doesnt work either. WithAllInterfaces() just find that I have an IService but the problem remains. My controllers needs the CountryServiceBase to be instantiated with a CountryService object. CountryService inherits CountryServiceBase, and CountryServiceBase Inheriste ServiceBase. – AMS Jun 15 '15 at 08:04
  • @AMS, `WithAllInterfaces` works for interfaces only. Could you provide class diagramme that you have right now. There might be no problem with `Windsor` api but with inheritance that you have in your application. – Ilya Palkin Jun 15 '15 at 18:34
  • Try using `Classes` instead of `Types`, as shown here: [Register types based on base class](http://stackoverflow.com/a/20356804). Combined with `BasedOn()` and `InSameNamespaceAs<>()` it should be possible to achieve the desired behavior. – Svein Fidjestøl Jun 15 '15 at 21:17

3 Answers3

1

Usually services are interfaces. That's why AllInterfaces() works for others.

If you check API you'll find Select() method that can be used easily.

If none of the above options suits you you can provide your own selection logic as a delegate and pass it to WithService.Select() method.

So registration code could be the following:

    container.Register(Types.FromThisAssembly()
        .BasedOn(typeof(ServiceBase<>))
        .WithService.AllInterfaces()
        .WithService.Select((t, b) => t.BaseType != null
                ? new[] { t.BaseType }
                : new Type[0])
        .LifestylePerWebRequest());

This solution is quite quick-and-dirty but at least it solves your issue.

Ilya Palkin
  • 14,687
  • 2
  • 23
  • 36
0

If your CountryServiceBase class is abstract, using Classes instead of Types should help to avoid having the base class registered (see here):

Classes on the other hand pre-filters the types to only consider non-abstract classes

However it does not look like you can avoid mentioning CountryServiceBase in your registration, maybe using OrBasedOn(CountryServiceBase) then your implementation will be available as both ServiceBase<> and CountryServiceBase.

Alexander Balabin
  • 2,055
  • 11
  • 13
0

You can use reflection to get all classes inheriting from your serviceBase. You can find a the way to do this here

Then you can implement the code above to instantiate all the services.

Community
  • 1
  • 1
Bilel Chaouadi
  • 903
  • 1
  • 10
  • 28
  • This could be an idea. I'll wait for the bounty to finish but I like this solution as I could add services without having to register them one by one as I create them on my project. – AMS Jun 15 '15 at 14:05