C # dynamic getter and setter depending on application context

We have a library of functions, and some utility variables are stored in two different ways, depending on the application / website of the application of the context application

On the website, we use Session and static desktop variables, and we would like to combine and automate the getters // settings for these variables without affecting performance too much.

Example:

public static class Cons { public static bool webMode; } public static class ConsWEB { public static string Username { get{ return HttpContext.Current.Session["username"].ToString();} set{ HttpContext.Current.Session["username"]=value;} } } public static class ConsAPP { private static string _username; public static string Username { get{ return _username;} set{ _username=value;} } } 

Solution 1, which we thought using IFs (it seems bad for performance, takes into account access to variables many times, and in some cases the variables are user classes with complex content):

 public static class Cons { public static bool webMode; public static string Username { get{ return webMode? ConsWEB.Username : ConsAPP.Username; } set { if(webMode) { ConsWEB.Username = value; } else { ConsAPP.Username = value; } } } } 

Solution 2 using delegates in the Static Class constructor binds delegated methods for each get and set, as appropriate. If webMode points to get / set methods ConsWEB, otherwise for get / set methods for ConAPP ...

Is solution 2 the best in performance? Are there other methods for these cases?

+4
source share
1 answer

None of them are optimal ...

First, forget about performance first, think about design.

You should do this through an interface or the like:

 public interface IConsProvider { string UserName { get; set; } } 

Now your implementations (NOTE: you should not compile for both desktop and web sites in one assembly. System.Web, for example, is not available in the client profile that you really should use for desktop applications).

 public class WebConsProvider : IConsProvider { public string UserName { // DON'T USE .ToString()! If it null you get NullReferenceException! get{ return HttpContext.Current.Session["username"] as string; } set{ HttpContext.Current.Session["username"]=value; } } } public class DefaultConsProvider : IConsProvider { public string UserName { get; set; } } 

And then your environment is static:

 public static class Cons { //initialise to default as well - only web apps need change it private static IConsProvider _provider = new DefaultConsProvider(); public static IConsProvider Provider { get { return _provider; } set { _provider = value; /* should check for null here and throw */ } } //if you really want you can then wrap the properties public static string UserName { get { return _provider.UserName; } set { _provider.UserName = value; } } } 

Now you have an extensible provider whose implementation you do not need to worry about.

I also have a problem with wrapping HttpContext.Current - however, in most scripts that work fine - if you have any asynchrony, however, you have to be careful.

Also, as I mentioned in my comments, now you no longer need to wrap properties as static in Cons . In fact, you get terrible multi-problem and extensibility by changing the code as follows:

 public void TraceUserName() { Trace.WriteLine(Cons.UserName ?? "[none]"); } 

For this:

 public void TraceUserName(IConsProvider provider) { Trace.WriteLine(provider.UserName ?? "[none]"); } 

Believe me, there will be times in your code when you want "just for this call, I would like to redefine the username," but I can’t, because this is a static property. "

Finally, you now have another extensibility mechanism that you don't use with statics: extension methods.

Suppose you add a generic storage engine to the interface for strings:

 string this[string key] { get; set; } 

So, for the row indexer, which allows us to implement vocabulary functionality for unexpected values. Suppose both of them were implemented with Dictionary<string, string> in DefaultConsProvider and wrapping Session in WebConsProvider ).

Now, if I am writing an additional module for your project that requires an additional string value, I can do this:

 public static MySettingsExtensions { public static string GetMySetting(this IConsProvider provider) { //TODO: argument null checks return provider["MySetting"]; } public static void SetMySetting(this IConsProvider provider, string val) { provider["MySetting"]=val; } } 

(Sorry, I had to update the last bit, because for some reason I parameterize the key - it was pointless!)

That is - now we can begin to expand the range of strongly typed settings offered by the provider, using extension methods - without having to change any source code.

+6
source

Source: https://habr.com/ru/post/1447469/


All Articles