Search code examples
c#nhibernatecastle-windsor

Interfaces are in a different project as implementations, castle not wiring up propertly


My Interfaces are in a seperate project, and I'm guessing I have to do something special when I am registering my services etc. in windsor.

The error I am getting is:

Type ABC.Interfaces.Services.IUserService is abstract.
As such, it is not possible to instansiate it as implementation of service ABC.Interfaces.Services.IUserService.

My installer:

 public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                    AllTypes.FromAssemblyContaining<UserService>()
                    .BasedOn<IUserService>()
                    .Where(type => type.Name.EndsWith("Service"))
                    .WithService.DefaultInterface()
                    .Configure(c => c.LifeStyle.Singleton));
        }

    container.Register(
                    AllTypes.FromAssemblyContaining<UserRepository>()
                    .BasedOn<IUserRepository>()
                    .Where(type => type.Name.EndsWith("Repository"))
                    .WithService.DefaultInterface()
                    .Configure(c => c.LifeStyle.PerWebRequest)
                    );

I was getting the error, and then I added the .BasedOn<....>() clause as I figured it has to do with my interfaces being in a separate project (and thus assembly) as the actual implementation.

Do I have to tell castle the assembly of that interface? Or is something else the issue?

Update II

My code:

public class HomeController : Controller
{
        private IUserService _userService;

        public HomeController(IUserService userService)
        {
            this._userService = userService;
        }

}

In services assembly:

public class UserService : IUserService
    {
        private IUserRepository _repository;

        public UserService(IUserRepository repository)
        {
            this._repository = repository;
        }


        public void Create(IUser user)
        {
            _repository.Create(user);
        }
        public IUser Get(int id)
        {
            return _repository.Get(id);
        }

    }

In interfaces assembly:

public interface IUserService
{
        void Create(IUser user);
        IUser Get(int id);
}

Solution

  • The problem is that BasedOn, Where, and Pick do logical or

    So this code:

    AllTypes.FromAssemblyContaining<UserService>()
        .BasedOn<IUserService>()
        .Where(type => type.Name.EndsWith("Service"))
    

    Will select all types that are based on IUserService, or end with Service. The type IUserService ends with Service, so it gets selected for registration.

    To solve this, you can remove the EndsWith("Service") filtering. It probably isn't necessary anyway. Or you could remove the BasedOn filter, and move similar logic to the Where clause:

    AllTypes.FromAssemblyContaining<UserService>()
        .Where(type => type.Name.EndsWith("Service")
            && typeof(IUserService).IsAssignableFrom(type))
        .WithService.DefaultInterface()
        .Configure(c => c.LifeStyle.Singleton)
    

    Also, you say the types are in different assemblies, but it seems somehow you are grabbing types out of the assembly that IUserService lives in.

    Check out this question for a way to debug which services are getting registered by your code.