简体   繁体   中英

castle windsor registering service and implementation only where implementation is not abstract or interface

All my services and their interfaces for the domain are within one project, repository in another. I use the following code to register the assemblies:

public IWindsorContainer SetupWithWebRequest()
{
    return Generate(c => c.LifestylePerWebRequest());
}

public WindsorContainer SetupWithThread()
{
    return Generate(c => c.LifestylePerThread());
}

private WindsorContainer Generate(Action<ComponentRegistration> reg)
{
    var container = new WindsorContainer();

    var types = new List<FromAssemblyDescriptor>();
    types.Add(Types.FromAssembly(typeof(BlogRepository).Assembly));
    types.Add(Types.FromAssembly(typeof(BlogEntryService).Assembly));

    foreach (var type in types)
    {
        container.Register(type.Pick().WithServiceAllInterfaces().Configure(reg));
    }

    //ensure the db context is passed in.
    container.Register(Component.For<IUserRepository<BlogUserEntity, int>>().LifeStyle.PerWebRequest.UsingFactoryMethod(() => new GenericUserRepository<BlogUserEntity, int>(new BlogEngineContext())));

   return container;
}

The above code will register lots of things that I am not interested about. For example everything that is IDisposable. This is probably not a problem, do wonder if it would slow things down a lot? My main issue is I have one interface defined in the domain layer but it is implemented in the website.

The code above is within the domain DLL and called from the website (global.asax), as below:

 var container = new WindsorContainerGeneration().SetupWithWebRequest();
 container.RegisterControllers(Assembly.GetExecutingAssembly());

 //setup the website to get its user from aspnet.
 container.Register(Component.For<IGetCurrentUserName>().LifeStyle.PerWebRequest.ImplementedBy(typeof(GetCurrentUserNameUsingAspnet)));

 GlobalConfiguration.Configuration.DependencyResolver = new WindsorDependencyResolver(container);
 ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));

even though I manually register the instance of IGetCurrentUserName the container will already have an instance registered where both the service and implementation are the interface.

Is there a way to ensure that only classes that implement an interface get registered rather than above?

You can filter to only classes that implement a specific interface using types.BasedOn<IInterfaceName>()

If you want to filter to only classes that implement any interface you could use this:

types.Where(type => type.GetInterfaces().Any() 

Here is an example implementation :

protected virtual IEnumerable<IRegistration> GetComponentRegistrations()
        {
            return new IRegistration[]
                {
                    Classes.FromAssembly(GetAssemblyNamed(MyAssembly))
                           .BasedOn<IMyComponent>()
                           .If(x => x.IsContructable()) // this is it
                           .WithServiceDefaultInterfaces()
                };
        }

public static class TypeHelpers
    {
        public static bool IsContructable(this Type t)
        {
            return !t.IsAbstract && !t.ContainsGenericParameters;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM