开发者

What is the simplest way to extend Castle windsor to support private constructors for every service

We want to be able to Resolve services using Castle for implementation with private constructors.

This is a fictive "use case" for that:

public class SingletonClass : ISingletonClass
{

   private SingletonClass() {...} // Class users cannot create an instance

   public ISingletonClass Instance 
   { 
      get 
      {
         // The intention here is to get an instance of this service
         // it has previously been configured as singleton in the container
         return Container.Resolve<ISingletonClass>();
      }
   } 
}

We want to have the option to use those private constructors for every service, not only for a few specific cases. Hence, we're looking for a simple and generic solution for this.

We looked for a solution using a custom component activator but found that we have to overrides a not-so trivial part of the default component activator, e.g. CreateInstance method.

This is the code for this in the default component activator:

    protected virtual object CreateInstance(CreationContext context, object[] arguments, Type[] signature)
    {
        object instance = null;
        Exception exception;
        Type implementation = base.Model.Implementation;
        bool flag = base.Kernel.ProxyFactory.ShouldCreateProxy(base.Model);
        bool flag2 = true;
        if (!(flag || !base.Model.Implementation.IsAbstract))
        {
            throw new ComponentRegistrationException(string.Format("Type {0} is abstract.{2} As such, it is not possible to instansiate it as implementation of {1} service", base.Model.Implementation.FullName, base.Model.Service.FullName, Environment.NewLine));
        }
        if (flag)
        {
            flag2 = base.Kernel.ProxyFactory.RequiresTargetInstance(base.Kernel, base.Model);
        }
        if (flag2)
        {
            try
            {
                if (this.useFastCreateInstance)
                {
                    instance = FastCreateInstance(implementation, arguments, signature);
                }
                else
                {
                    instance = ActivatorCreateInstance(implementation, arguments);
                }
            }
            catch (Exception exception1)
            {
                exception = exception1;
                throw new ComponentActivatorException("ComponentActivator: could not instantiat开发者_JAVA技巧e " + base.Model.Implementation.FullName, exception);
            }
        }
        if (flag)
        {
            try
            {
                instance = base.Kernel.ProxyFactory.Create(base.Kernel, instance, base.Model, context, arguments);
            }
            catch (Exception exception2)
            {
                exception = exception2;
                throw new ComponentActivatorException("ComponentActivator: could not proxy " + base.Model.Implementation.FullName, exception);
            }
        }
        return instance;
    }

It would be much easier if we could only overrides "ActivatorCreateInstance" or "FastCreateInstance" but they're closed.

Are we on the wrong track?

Is there a much simpler way to do this in a generic manner?

Thank you very much

Phil


Since it's an open-source project, you can write your own component activator by copying and pasting the DefaultComponentActivator code, changing what you need and registering the activator. I've done it a few times with several other components of the Castle stack. When it's done, send in a patch.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜