Какой самый простой способ расширить Castle Windsor для поддержки частных конструкторов для каждого сервиса - PullRequest
0 голосов
/ 12 марта 2010

Мы хотим иметь возможность разрешать службы, используя Castle для реализации с частными конструкторами.

Это вымышленный «вариант использования» для этого:

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>();
      }
   } 
}

Мы хотим иметь возможность использовать эти частные конструкторы для каждого сервиса, а не только для нескольких конкретных случаев. Следовательно, мы ищем простое и универсальное решение для этого.

Мы искали решение, использующее специальный активатор компонента, но обнаружили, что нам нужно переопределить не так тривиальную часть активатора компонента по умолчанию, например, Метод CreateInstance.

Это код для этого в активаторе компонента по умолчанию:

    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;
    }

Было бы намного проще, если бы мы могли только переопределить «ActivatorCreateInstance» или «FastCreateInstance», но они закрыты.

Мы на неправильном пути?
Есть ли гораздо более простой способ сделать это в общем виде?

Большое спасибо
Фил

1 Ответ

0 голосов
/ 30 июля 2010

Поскольку это проект с открытым исходным кодом, вы можете написать свой собственный активатор компонента, скопировав и вставив код DefaultComponentActivator, изменив то, что вам нужно, и зарегистрировав активатор. Я делал это несколько раз с несколькими другими компонентами стека Castle. Когда это будет сделано, отправьте патч.

...