Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Castle.Windsor DI container [Working code] #263

Closed
egorpavlikhin opened this issue Jan 9, 2015 · 7 comments
Closed

Castle.Windsor DI container [Working code] #263

egorpavlikhin opened this issue Jan 9, 2015 · 7 comments

Comments

@egorpavlikhin
Copy link

If anyone is interested I've adapted current autofac code to work with Castle.Windsor container. Can't be bothered to do an official pull request, so here it goes.

public static class WindsorRegistration
{
    public static void Populate(
            this IWindsorContainer container,
            IEnumerable<IServiceDescriptor> descriptors)
    {
        container.Register(Component.For<IWindsorContainer>().Instance(container));
        container.Register(Component.For<IServiceProvider>().ImplementedBy<WindsorServiceProvider>());
        container.Register(Component.For<IServiceScopeFactory>().ImplementedBy<WindsorServiceScopeFactory>());

        container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

        Register(container, descriptors);
    }

    private static void Register(
            IWindsorContainer container,
            IEnumerable<IServiceDescriptor> descriptors)
    {
        foreach (var descriptor in descriptors)
        {
            if (descriptor.ImplementationType != null)
            {
                // Test if the an open generic type is being registered
                var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
                if (serviceTypeInfo.IsGenericTypeDefinition)
                {
                    container.Register(Component.For(descriptor.ServiceType)
                                            .ImplementedBy(descriptor.ImplementationType)
                                            .ConfigureLifecycle(descriptor.Lifecycle)
                                            .OnlyNewServices());
                }
                else
                {
                    container.Register(Component.For(descriptor.ServiceType)
                                            .ImplementedBy(descriptor.ImplementationType)
                                            .ConfigureLifecycle(descriptor.Lifecycle)
                                            .OnlyNewServices());
                }
            }
            else if (descriptor.ImplementationFactory != null)
            {
                var service1 = descriptor;
                container.Register(Component.For(descriptor.ServiceType)
                        .UsingFactoryMethod<object>(c =>
                        {
                            var builderProvider = container.Resolve<IServiceProvider>();
                            return
                                service1.ImplementationFactory(builderProvider);
                        })
                        .ConfigureLifecycle(descriptor.Lifecycle)
                        .OnlyNewServices());
            }
            else
            {
                container.Register(Component.For(descriptor.ServiceType)
                        .Instance(descriptor.ImplementationInstance)
                        .ConfigureLifecycle(descriptor.Lifecycle)
                        .OnlyNewServices());
            }
        }
    }

    private static ComponentRegistration<object> ConfigureLifecycle(
            this ComponentRegistration<object> registrationBuilder,
            LifecycleKind lifecycleKind)
    {
        switch (lifecycleKind)
        {
            case LifecycleKind.Singleton:
                registrationBuilder.LifestyleSingleton();
                break;
            case LifecycleKind.Scoped:
                registrationBuilder.LifestyleScoped();
                break;
            case LifecycleKind.Transient:
                registrationBuilder.LifestyleTransient();
                break;
        }

        return registrationBuilder;
    }

    private class WindsorServiceProvider : IServiceProvider
    {
        private readonly IWindsorContainer _container;

        public WindsorServiceProvider(IWindsorContainer container)
        {
            _container = container;
        }

        public object GetService(Type serviceType)
        {
            return _container.Resolve(serviceType);
        }
    }

    private class WindsorServiceScopeFactory : IServiceScopeFactory
    {
        private readonly IWindsorContainer _container;

        public WindsorServiceScopeFactory(IWindsorContainer container)
        {
            _container = container;
        }

        public IServiceScope CreateScope()
        {
            return new WindsorServiceScope(_container);
        }
    }

    private class WindsorServiceScope : IServiceScope
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IDisposable _scope;

        public WindsorServiceScope(IWindsorContainer container)
        {
            _scope = container.BeginScope();
            _serviceProvider = container.Resolve<IServiceProvider>();
        }

        public IServiceProvider ServiceProvider
        {
            get { return _serviceProvider; }
        }

        public void Dispose()
        {
            _scope.Dispose();
        }
    }
}

It fits in like this:

app.UseServices(services => {
            // Add EF services to the services container.
            services
                .AddEntityFramework(Configuration)
                .AddSqlServer()
                .AddDbContext<ApplicationDbContext>();

            // Add Identity services to the services container.
            services
                .AddIdentity<ApplicationUser, IdentityRole>(Configuration)
                .AddDefaultTokenProviders();

            // Add MVC services to the services container.
            services
                .AddMvc();

            container.Populate(services);

            container.BeginScope();

            return container.Resolve<IServiceProvider>();
        });
@davidfowl
Copy link
Member

@egorpavlikhin so are you gonna send a pull request 😄

@Praburaj
Copy link

Will be good to have an entropy sample.

@egorpavlikhin
Copy link
Author

@davidfowl will do, give me some time.

@egorpavlikhin
Copy link
Author

So Castle.Windsor doesn't support nested scopes, but DI unit tests require that they do work and resolve to different services. Any ideas on how to proceed?

@egorpavlikhin
Copy link
Author

@halter73
Copy link
Member

@egorpavlikhin I think perhaps we can remove the requirement to support nested scopes.

Does anyone know of anything currently relying on nested scopes?

@danroth27
Copy link
Member

Let's continue this discussion in the DependencyInjection repo (aspnet/DependencyInjection#160) as needed.

natemcmaster pushed a commit that referenced this issue Nov 14, 2018
Can't use dispose (or close) as can be disposed too early by user code

Resolves #263
ryanbrandenburg pushed a commit that referenced this issue Nov 16, 2018
Update configuration for Identity
ryanbrandenburg pushed a commit that referenced this issue Nov 22, 2018
ryanbrandenburg pushed a commit that referenced this issue Nov 27, 2018
@ghost ghost locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants