Search code examples
asp.netcastle-windsorcastle

Functionality change while upgrading to Castle Windsor 3.3.0 from 3.2.0


I am attempting to migrate from version 3.2.0 to 3.3.0. I am getting a compile error. I could not find an entry in the "Breaking Changes" section but here are my two errors in hope someone can guide me to a workable alternative.

public void RegisterTypeSingleton<T>(Type component, string name)
{
    if (_container.Kernel.HasComponent(name))
        _container.Kernel.RemoveComponent(name);    
    _container.Register(Component.For<T>().ImplementedBy(component).Named(name).LifeStyle.Singleton);    
}
  1. It seems Kernel.RemoveComponent() function has been depreciated. What has replaced this?

  2. The second compiler error is at _container.Register(Component.For<T>().ImplementedBy(component).Named(name).LifeStyle.Singleton);

    • I am getting "The Type 'TService' must be a reference type in order to use it as a parameter.

Solution

  • I think you might be upgrading from an older version than 3.2.0. See below.

    1. The removal of IKernel.RemoveComponent() is documented in the Breaking Changes document with v3.0.0. Here is the extract where Krzysztof explains why it was removed:

      change - Removed the following methods:
          GraphNode.RemoveDepender,
          GraphNode.RemoveDependent,
          IKernel.RemoveComponent,
          IKernelEvents.ComponentUnregistered,
          INamingSubSystem.this[Type service],
          INamingSubSystem.GetHandler,
          INamingSubSystem.GetService2Handler,
          INamingSubSystem.GetKey2Handler,
          INamingSubSystem.UnRegister(String key),
          INamingSubSystem.UnRegister(Type service)
       Also INamingSubSystem.Register now takes only IHandler as its argument
      
      impact - low
      fixability - none
      
      description - The methods were implementation of "remove component from the container" feature
          which was flawed and problematic, hecen was scraped.
      
      fix - Working around is quite dependant on your specific usage. Try utilizing IHandlerSelectors.
          For changed Register method, just update your calling code not to pass the name.
          handler.ComponentModel.Name is now used as the key, as it was happening in all places so far
          anyway, so this change should have no real impact.
      

      RegisterComponent() won't overwrite an existing service registration, it'll just register another component for the same service, unless you specify the same name where it'll throw an exception informing you there is another component registered with that name. If your application doesn't replace components very often you could use the IsDefault() method on the registration to get Windsor to resolve the new component by default, just note the other component is still registered.

      If your application replaces components often and you don't want the other registrations left there, you'd be best using a custom IHandlerSelector or ISubDependencyResolver so Windsor will ask you each time what component you want used for a specific service.

    2. Also in v3.0.0 a change was made to ensure that value types cannot be passed to the registration methods. You'll need to add a generic constraint to your method that accepts a generic parameter so that it also only accepts reference types:

      public void RegisterTypeSingleton<T>(Type component, string name)
          where T : class
      {
          ...
      }