简体   繁体   中英

Castle Windsor Update Instance Property

I'm trying to use Castle Windsor to reuse a single instance of my WebApp settings class ( MySettings ). This settings rarely changes, but when it changes, I need to update the instance in the container. I can easily track when the Settings changes, but I can't figure out the right way to do it, can anybody help me?

The Windsor Installer class is bellow:

public class SettingsInstaller : IWindsorInstaller
{
    private MySettings Settings { get; set; }

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        UpdateSettings();

        container.Register(
            Component.For<MySettings>()
            .Instance(this.Settings));
    }

    public MySettings UpdateSettings()
    {
        using (DbContext db = new DbContext())
        {
            this.Settings = db.Settings.FirstOrDefault();
        }

        return this.Settings;
    }
}

How can I call the UpdateSettings() and make sure that the container will use the updated Settings in the next Dependency Injection resolution?

I had no answer yet. I have done this, and it is working:

public class SettingsInstaller : IWindsorInstaller
{
    private static MySettings Settings { get; set; }

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        UpdateSettings();

        container.Register(
            Component.For<MySettings>()
            .UsingFactoryMethod(() =>
            {
                return SettingsInstaller.Settings;
            })
            .LifestyleTransient());
    }

    public static MySettings UpdateSettings()
    {
        using (DbContext db = new DbContext())
        {
            SettingsInstaller.Settings = db.Settings
                .AsNoTracking()
                .FirstOrDefault();
        }

        return SettingsInstaller.Settings;
    }
}

I think what you want is for MySettings to be a singleton whose state you can then update in other parts of the application. If you register MySettings as a singleton, then whenever the container resolves a MySettings for you, it will return the same instance. This is essentially what you are doing in your answer, but you're just storing the instance in a local variable (instead of letting the container do it for you).

Your registration code can then get very simple:

public class SettingsInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
         container.Register(Component.For<MySettings>().LifestyleSingleton());
    }
}

Whenever you need to access the settings, you can request a MySettings from the container using constructor injection (or any other method of getting an instance from a container):

public class ClientClass
{
    private readonly MySettings _settings;

    public ClientClass(MySettings settings)
    {
         _settings = settings;
    }

    public void UpdateSettings()
    {
         _settings.SomeSetting = myNewSetting; // reset them however you need to here
    }
}

After you've called UpdateSettings() in your application somewhere, then the instance the container is holding on to (a singleton) will be updated with myNewSetting, and when the next class requests a MySettings you'll get the same instance with the updated value.

If you actually need a new instance of MySettings, then in your UpdateSettions() method you can create an entirely new one using _settings = new MySettings() and the container will serve up the new instance for you from then on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM