9

I have a class in a web application I am working on that holds client settings. For some background, I do not own this class, and changing it is not an option. We recently added some logic to store the settings in a database, and I was tasked with creating a page to edit them, fair enough.

Here is my issue; the settings are held in a static class, and are themselves static, read-only properties. For example

public static class Settings
{
 public static readonly setting1 = SettingmanagerClass.GetSetting("setting1");
 public static readonly setting2 = SettingmanagerClass.GetSetting("setting2");
 public static readonly setting3 = SettingmanagerClass.GetSetting("setting3");
}

Now, for example, through the page I wrote, we change the value for setting2 to "Happy Variable"; it saves to the DB just fine, but now I need it to be reflected in the web app as the new value. Since it is a static readonly property of a static class, it only ever gets called when the app first wires up and can't be set manually.

Just to reiterate, I don't own the original class, so "just make the properties writeable" is not (currently) a valid option. Normally I would just talk this over with my boss and he would make a judgement call and possibly allow me to modify the other class, but I am not in a position to make that call and he is out of the office for the week.

So basically; is there any way to re-initialize a static class once a web application has started running? I just need for it to reload all of its properties as if the app was just rebuilt and started up again.

7
  • You can change it with reflection or recycle the process. Here is a thread on how to do reflection: Commented Apr 23, 2012 at 15:05
  • Just a side-note: You know that all settings(f.e. from web.config) are cached anyway? Commented Apr 23, 2012 at 15:07
  • Is it possible to restart your IIS? Start or Stop an Application Pool (IIS 7) Commented Apr 23, 2012 at 15:09
  • Best bet is reflection or bouncing the IIS AppDomain to bin the statics. Both of which are detailed below. When your boss gets back, get approval to put a proper solution in place and get rid of the static readonly members. Be careful, I've seen and still see plenty of "temporary hacks" that are older than my programming career. Commented Apr 23, 2012 at 15:13
  • 1
    Really, anything suggested is going to be far more ugly than making them writable, I know you said that's "not (currently) a valid option", but it would be the cleanest... Commented Apr 23, 2012 at 15:14

8 Answers 8

16
  ConstructorInfo constructor = typeof(Settings).GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,null, new Type[0], null);
  constructor.Invoke(null, null);
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I tested with OPs class to make sure than posted :)
I tired this one, and I absolutely worked, but the web app for some weird reason continued to load the original values in the pages despite the debugger showing the updated value. Very weird, and although I didn't use it this time, I will hold on to that one, it is great, even if it's purely for academic reasons (for me) right now.
That's evil. Thought I was going to have to refactor my cache class, but black magic it is, thanks,
Thank you. This is evil, but it works. Reflection is scary
5

You could use reflection:

var prop = typeof(Settings).GetField("setting1", BindingFlags.Static | 
                                                 BindingFlags.Public);
prop.SetValue(null, "Bar");
string currentValue = Settings.setting1; //Bar

Comments

2

If the above code is representative of the situation you're in, you won't be able to reinitialize the code unless you do something particularly hacky with reflection (this is not recommended by the way).

Edit: Oh wait - I didn't realize this was a web app. You could programmatically bounce the application:

System.Web.HttpRuntime.UnloadAppDomain

6 Comments

This could be dangerous though if other users are in the system and the session is lost due to bounce.
I actually just tested this against the scenario I laid out in the original post and it worked; no loss of session at all, just the settings reloaded. Perfect. I have tested it a few times to make sure I am not just being excited over a perceived success, but from what I can see, this is pure win, thank you!
@ddietle - I'm glad this is working for you, but am puzzled as to how your sessions weren't destroyed. Are you storing your session out of process (e.g. in SQL Server)?
That is exactly how they handle it (SQL State server). I guess it was luck of the draw on my part.
UPDATE: I was (luckily) able to get permission to handle this is the "right" way and I will be changing the properties from readonly to standard properties with get and set. huge sigh of relief
|
1

The only option comes to my mind which is requires a lot of work:

  1. Create another AppDomain
  2. Load assembly in the other domain
  3. Use Remoting to get the data
  4. If settings changed, unload the AppDomain and do steps 1 to 3 again

Comments

1

I would use reflection

var info = typeof(Settings)
.GetField("Settings",BindingFlags.Static|BindingFlags.Public);
info.SetValue(null, "setting4");

Comments

1
public static class Settings
{
   public static name = "";

   static Settings()
   {
    ReInitialize();
   }

   public static void ReInitialize()
   {
      name = "My name is re-initialized";
   }
}


Settings.name = "My name has changed";
// Console.WriteLine(Settings.name);
Settings.ReInitialize(); //name is "My name is re-initialized"
// Console.WriteLine(Settings.name);

Comments

0

Hmm, you want to find a way to hack the class? even if it exists with reflection and something like that, it is not good way to solve this

Fast workaround I can suggest to create you own not readonly static properties, initialize with that static variables and use them everywhere

But it will be better to use Cache or Application stores instead of static variables

Hope this helps

2 Comments

Using the session isn't an appropriate place for data that is scoped to the entire application. Also, the OP stated that he doesn't own the offending code.
Edited, sure @RQDQ, Application or cache will be better
0

Old thread I know, but one thing I have done is to create an Initialize method (public static void) that sets all of the variables (they're all public static). In that method, the database calls are made and the variables of the class are set. Then in code, anytime you want to refresh the variables (i.e. anytime you call SaveChanges()), you can call Class.Initialize() and you're done.

I use this for caching common lists of lookup information that can change, and we need to keep that in sync for when the database is updated from the application.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.