Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove component in CastleWindsor version >3.0 #151

Open
IhorHolovatsky opened this issue Oct 20, 2016 · 2 comments
Open

Remove component in CastleWindsor version >3.0 #151

IhorHolovatsky opened this issue Oct 20, 2016 · 2 comments

Comments

@IhorHolovatsky
Copy link

IhorHolovatsky commented Oct 20, 2016

Reffer to #98

I got the same issue

As we know, from CastleWindsor 3.0 version, we don't have RemoveComponent method in IKernel.

We can register component, but we can't remove it.

My Situation:
We use CastleWindsor 3.3 version
We have Application that runs all time.
This Application dynamically scans folder D:\FolderName finds *.dll files, and registers components for our IAction service. For component name - we use name of .dll file
If dll file was not changed - we get component from container.
But if dll file was changed - we need to remove previous component, and register new one.
The problem is that we can't remove previous component, since CastleWindsor 3.0 version doesn't have RemoveComponent method.
As a result, if dll will change 1000 times, we will have 1000 unused components. Since our Application runs all time, we will have lack of memory eventually.

Temporary we solve this problem by disposing WindsorContainer, if dll was changed. (But in this case performance decreases)

Dear developers, can we hope for some method in CastleWindsor for remove component in new versions?
I'm sorry if I miss something, and there are a way how to remove component in CastleWindsor 3.3. Please, advice

@mikeobrien
Copy link

I ran into the same exact problem, had to override registration of a container I did not have control over and for some reason I could not get .IsDefault to work. What I ended up doing is swapping out the kernel's naming subsystem with one that allows you to delete registrations (not sure why this was removed ಠ_ಠ). Only potential gotcha is that it doesn't copy over filters or selectors from the original subsystem but I guess that's not an issue if you don't use them.

Extension methods:

public static class CastleExtensions
{
    public static IWindsorContainer RemoveHandler<T>(this IWindsorContainer container)
    {
        container.EnsureRemovableNamingSubSystem().RemoveHandler<T>();
        return container;
    }

    private static RemovableNamingSubSystem EnsureDeletableNamingSubSystem(
        this IWindsorContainer container)
    {
        var key = SubSystemConstants.NamingKey;
        var naming = container.Kernel.GetSubSystem(key) as INamingSubSystem;
        var removableNaming = naming as RemovableNamingSubSystem;
        if (removableNaming != null) return removableNaming;
        removableNaming = new RemovableNamingSubSystem(naming);
        container.Kernel.AddSubSystem(key, removableNaming);
        return removableNaming;
    }
}

Removable naming subsystem:

public class RemovableNamingSubSystem : DefaultNamingSubSystem
{
    public RemovableNamingSubSystem(INamingSubSystem namingSubSystem)
    {
        namingSubSystem.GetAllHandlers().ForEach(Register);
    }

    public void RemoveHandler<T>()
    {
        var type = typeof(T);
        var invalidate = false;
        using (@lock.ForWriting())
        {
            if (name2Handler.ContainsKey(type.FullName))
            {
                invalidate = true;
                name2Handler.Remove(type.FullName);
            }
            if (service2Handler.ContainsKey(type))
            {
                invalidate = true;
                service2Handler.Remove(type);
            }
            if (invalidate) InvalidateCache();
        }
    }
}

@Echtelion
Copy link

Echtelion commented Nov 20, 2020

Hello,

I'm sorry to reopen this old ticket, but the latest version of castle changed InvalidateCache to private.
It's also not possible to reimplement it in the derived method, because the fields are also made private and the property are protected read only. Ultimately, assignableHandlerListsByTypeCache is private with no protected accessor at all.

I can reimplement it with reflection, as I'm not using this method intensively, but is there a new recommended way to do this ?

Regards, (edit : created a new issue referencing this one)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants