views:

243

answers:

1

Hi there,

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 instantiate " + 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

A: 

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.

Fábio Batista