Question

I'm trying to figure out Windsor as an IOC container. The problem I'm facing right now is to register all of my viewmodels at once.

I've taken a look at the docs and thought that the following code should work. However, when I check the container afterwards, nothing is registered.

container.Register(Classes.FromThisAssembly()
                          .BasedOn<ViewModelBase>()
                          .LifestyleTransient());

where ViewModelBase is my baseclass.

Also tried the following:

container.Register(Classes.FromThisAssembly()
         .InSameNamespaceAs<MainWindowViewModel>()
         .LifestyleTransient()); 

The necessary dependencies can be resolved, the viewmodels not. I suppose I'm missing something obvious here?

Edit

My dependencies are registered as follows:

this.container.Register(Component.For<IDALHandler>().ImplementedBy<DALHandler>());
this.container.Register(Component.For<IBLHandler>().ImplementedBy<BLHandler>());

UPDATE

Since the suggestions didn't work, I was planning on adding the code from my baseclass and viewmodel here. While doing so I noticed that my viewmodel-class was internal sealed. When changing it to public sealed, the above code did work.

Can someone explain why internal classes can't be registered in the container? I've already tested other IOC containers with the exact same setup and they didn't complain about it.

Was it helpful?

Solution

Your example of registration started working well in my application when I added selection of the service for component. E.g. .WithService.AllInterfaces()

container.Register(Classes.FromThisAssembly()
    .BasedOn(typeof(MyBaseClass<>))
    .WithService.AllInterfaces()
    .LifestylePerWebRequest()
);

container.Register(Classes.FromThisAssembly()
    .InSameNamespaceAs<MyBaseClass>()
    .WithService.AllInterfaces()
    .LifestylePerWebRequest()
);

UPDATE:

In order to register internal types, .IncludeNonPublicTypes() should be used.

public class ExampleTest
{
    [Test]
    public void MyBaseClass_Base()
    {
        var target = new WindsorContainer();

        target.Register(Classes.FromThisAssembly()
            .IncludeNonPublicTypes()
            .BasedOn(typeof(MyBaseClass<>))
            .WithService.Base()
            //.LifestylePerWebRequest()
        );

        //assert
        target.Resolve<MyBaseClass<int>>().Should().BeOfType<A>();
        target.Resolve<MyBaseClass<string>>().Should().BeOfType<B>();
    }

    [Test]
    public void MyBaseClass_Self()
    {
        var target = new WindsorContainer();

        target.Register(Classes.FromThisAssembly()
            .IncludeNonPublicTypes()
            .BasedOn(typeof(MyBaseClass<>))
            .WithService.Self()
            //.LifestylePerWebRequest()
        );

        //assert
        target.Resolve<MyBaseClass<int>>().Should().BeOfType<MyBaseClass<int>>();
        target.Resolve<MyBaseClass<string>>().Should().BeOfType<MyBaseClass<string>>();
        target.Resolve<A>().Should().BeOfType<A>();
        target.Resolve<B>().Should().BeOfType<B>();
    }
}

internal class MyBaseClass<T>
{
}

internal class A : MyBaseClass<int>
{
}

internal class B : MyBaseClass<string>
{
}

OTHER TIPS

My guess is your viewmodels have been registered in the container, but they are not resolvable through their interface.

Set a breakpoint after the registration and check if container has been filled as expected.

UPDATE as per my comment below: Keep in mind "group" registration (Classes.) skips internal class.

If they have been registered, let say you have a ViewModel like this

public class MyViewModel1 : ViewModelBase, IMyViewModel1


container.Resolve<MyViewModel1>() // resolve

container.Resolve<IMyViewModel1>() // no resolve

to accomplish the second resolving scenario you have to do what Ilya pointed about about adding WithService during registration, so you can resolve by interface instead of by concrete.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top