Castle Windsor: Register class with internal constructor?

后端 未结 3 494
慢半拍i
慢半拍i 2021-01-21 05:20

A Castle Windsor question: Is it possible to register a class that has an internal constructor with the container?

Thanks Joni

3条回答
  •  北恋
    北恋 (楼主)
    2021-01-21 06:07

    Following the accepted answer's advice, I was able to extend the DefaultComponentActivator class to work with protected constructors (it still does not work with private or internal; the code below works fine, that is, but something else in the DynamicProxy creation chain fails).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using Castle.Core;
    using Castle.MicroKernel;
    using Castle.MicroKernel.ComponentActivator;
    using Castle.MicroKernel.Context;
    
    namespace /* YourNameSpaceHere */
    {
        [Serializable]
        public class NonPublicComponentActivator : DefaultComponentActivator
        {
            public NonPublicComponentActivator(ComponentModel model, IKernelInternal kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
                : base(model, kernel, onCreation, onDestruction)
            { /* do nothing */ }
    
            private readonly List loadedTypes = new List();
            protected override ConstructorCandidate SelectEligibleConstructor(CreationContext context)
            {
                lock (loadedTypes)
                {
                    if (!loadedTypes.Contains(context.RequestedType))
                    {
                        loadedTypes.Add(context.RequestedType);
    
                        // Add the missing non-public constructors too:
                        var ctors = context.RequestedType.GetConstructors
                        (
                            BindingFlags.NonPublic | BindingFlags.Instance
                        );
    
                        foreach (var ctor in ctors)
                        {
                            Model.AddConstructor
                            (
                                new ConstructorCandidate
                                (
                                    ctor,
                                    ctor.GetParameters().Select(pi => new ConstructorDependencyModel(pi)).ToArray()
                                )
                            );
                        }
                    }
                }
    
                return base.SelectEligibleConstructor(context);
            }
        }
    }
    

    Then, on your container you register this against a ComponentRegistration object via the generic Activator method, so my container.Register call looks something like this:

        _container.Register
        (
            // . . .
    
            AllClasses.FromThisAssembly().BasedOn()
                .Configure
                (
                    c => c.LifeStyle.Transient
                        .Interceptors()
                        .Activator() // <--- REGISTERED HERE
                ),
    
            // . . .
        );
    

    Hope that helps someone!

提交回复
热议问题