I have static class that holds some info
public static class SampleDataCache
{
private static Dictionary<string,SampleData> cacheDict = new Dictionary<string,object>()
public static Get(string key)
{
if(!cacheDict.Contains[key])
cacheDict.Add(key,new SampleData());
return cacheDict[key];
}
}
And when I refresh page I want SampleDataCache to keep its data.
Can I achieve this in simple way?
Since the cache, in its current form, is stored in memory then the data is naturally cast into oblivion when the page refreshes - that's a new instance of the application starting there. You might, however, be interested in utilising isolated storage in order to persist data per-user.
With isolated storage you essentially have a contained file system into which you can store data and then further retrieve it. One step in the right direction could be to make a class you want to represent a 'piece' of cached data, make it serializable, then using your static class as the cache controller you can read and write these objects from and to isolated storage.
Quickstart: Isolated Storage in Silverlight
You should remember about extra if (nobody understand that ;/). And also you can be more generic and type safely. You can Look below, this is example of well written caching pattern also can be used as an aspect.
using System;
using System.Collections.Generic;
namespace SampleDataCache {
public class SampleData {
public string Name { get; set; }
}
public static class DataCache {
private static readonly Dictionary<string, object> CacheDict
= new Dictionary<string, object>();
private static readonly object Locker = new object();
public static T Get<T>(string key, Func<T> getSampleData) {
if (!CacheDict.ContainsKey(key)) {
lock (Locker)
if (!CacheDict.ContainsKey(key)) {
CacheDict.Add(key, getSampleData());
}
}
return (T)CacheDict[key];
}
}
public class Program {
private static SampleData CreateSampleData() {
return new SampleData() { Name = "Piotr Sowa" };
}
private static void Main(string[] args)
{
SampleData data = DataCache.Get("Author", CreateSampleData);
}
}
}
Regards
Related
I created a C# code for logging error codes.
I hardcoded the error codes into a class RecordId as static ints.
public class RecordId
{
public static int UnknownCommand = 100;
public static int SoftwareVersion = 101;
public static int WarningError = 110;
public static int AbortError = 111;
// etc...
}
Having static int means that I can do RecordId.SoftwareVersion anywhere in my code, I don't actually need to instantiate the class RecordId, which is very convenient, since I want to be able to log things from different parts of the code by calling a Log class that also doesn't need instantiation (it just appends a message to a file)
The logging function is also static, being something like
public class Logger
{
public static void LogExperiment(int key, string value)
{
// Append key and value to a hardcoded filename
}
}
Then from anywhere in my code I can do
Logger.LogExperiment(RecordId.SoftwareVersion, "1.0");
This will just append 101 1.0 in a log file
I don't need instances of the classes, so I can log anywhere from my code.
Now, as the code grows, I don't want to modify the code every time I add a new RecordId, so I want to have a JSON file where I load the values into the class.
I modified the RecordId class to look like:
public class RecordIdNew
{
public String UnknownCommand { get; set; }
public String SoftwareVersion { get; set; }
public String WarningError { get; set; }
public String AbortError { get; set; }
}
The problem I see now, is that in order to populate this values from the JSON file I have to instantiate the class RecordId, whereas before I was using the values as static ints, and therefore I could call RecordId.SoftwareVersion
The question (which might be a bit open) is: Is there a way I can keep RecordId not instantiated, but access values that come from a JSON file.
Or if not possible, is there another structure that would allow me to do that?
You are looking for static constructor, i.e.
// Let's have class being static if you don't want to create instances
public static class RecordId
{
// To be on the safer side of the road, let's have readonly fields:
// once set in the static constructor they can't be changed
public static readonly int UnknownCommand;
public static readonly int SoftwareVersion;
public static readonly int WarningError;
public static readonly int AbortError;
// Static constructor, it will be called before the first read of any field
static RecordId() {
//TODO: put your logic here: read the file and assign values to the fields
}
}
Edit:
Please, have a look at the your current design, maybe you are looking for {Key, Value} pairs? E.g. Key == 100, Value == "UnknownCommand" etc.
If it's your case, try using Dictionary:
public static class RecordId {
private static readonly Dictionary<int, string> s_Names = new();
public IReadOnlyDictionary<int, string> Names => s_Names;
static RecordId() {
//TODO: Your logic here (fill in s_Names)
}
}
usage:
int code = 100;
if (RecordId.Names.TryGetValue(code, out var name))
Console.WriteLine($"{code} is {name}");
else
Console.WriteLine("Unknown code");
Assuming you can perfectly match up the static C# properties or fields to the values in the JSON, you can use ModuleInitializerAttribute to set the static properties.
public static class RecordId
{
public static int UnknownCommand { get; private set; }
public static int SoftwareVersion { get; private set; }
public static int WarningError { get; private set; }
public static int AbortError { get; private set; }
// etc...
[ModuleInitializer]
public static void Init()
{
// code to read JSON
// loop over JSON fields, matching them to
// above fields, setting their values...
}
}
This gives you a way to set the values at runtime, once, when the module loads (modules are groups of logical code in an assembly (reference)).
Module initializers are guaranteed to be run before any other access to the module; so if you reference, say, UnknownCommand anywhere, you will get the value that was read from the JSON. In fact, as Dmitry notes in the comments, the module init code is guaranteed to run period, even if no other code in the module is accessed at all. This could be a drawback if the code is slow or buggy, but useful in cases such as yours.
This does not give you a way to dynamically create the properties; that would require either code generation prior to compilation or access to the values at runtime via some sort of "Get" method coupled with a static dictionary.
Here's an article on the subject, and here's the original proposal on GitHub.
I have a Configuration class that stores certain variables which serve as settings. And I'm struggling to find easiest and most optimal way to save it to file - would be weird if user had to configure it every time.
Example class:
public static Configuration
{
public static bool A = false;
public static bool B = false;
public static int C = 100;
}
Serializing collection is not an issue, but i cannot really make collection out of these variables, since they have not matching data types.
I'm certain solution is simple, but for some reason I'm stuck here.
Elaborating on my comment, you're better off converting your static class into an instance class for minimizing manual coding to store/read the property values in the future. This refactoring can be done in minutes. So do that as a first step, it shouldn't take too long to do, and a simple "Find/Replace" can fix all of your declarations everywhere in your code where you previously used "Configuration".
Keep your implementation static, but change to a single instance that you are accessing.
public class Configuration
{
private static Configuration instance;
public static Configuration Instance
{
get
{
if (instance == null)
{
instance = new Configuration();
}
return instance;
}
set
{
instance = value;
}
}
public bool A { get; set; }
public bool B { get; set; }
public int C { get; set; }
}
Do a Find/Replace where ever you declared your static class and replace "Configuration." with "Configuration.Instance.". Also, where you previously declared static properties like public static bool A; public static bool B; ... just select all of the text, do a Find/Replace and replace "static " with "".
Save/Read your data
// To Save
File.WriteAllText(#"c:\temp\myconfig.json", Newtonsoft.Json.JsonConvert.SerializeObject(Configuration.Instance));
// To Read
using (var file = File.OpenText(#"c:\temp\myconfig.json"))
{
JsonSerializer serializer = new JsonSerializer();
Configuration.Instance = (Configuration)serializer.Deserialize(file, typeof(Configuration));
}
I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.
I am thinking what is the best way to load data to collections if it is global per application;
public static class ErrorValues
{
public static readonly Dictionary<int, string> errorInfo = new Dictionary<int, string>
{
{0, "Error 404"},
{1, "Error 500"},
{2, "Error 301"}
};
}
or like this
public static class ErrorValues
{
public static Dictionary<int, string> errorInfo;
static ErrorValues()
{
if (errorInfo == null)
{
errorInfo = LoadDataToDictionary();
}
}
}
better solutions? Why?
If your data is static, I recommend creating a meaningful type
Example:
public class ErrorValue
{
private static Dictionary<Int32, ErrorValue> _errors;
public static readonly ErrorValue Error404 = new ErrorValue(404, "Error 404");
public static readonly ErrorValue Error500 = new ErrorValue(500, "Error 500");
public static readonly ErrorValue Error301 = new ErrorValue(301, "Error 301");
public String ErrorName { get; private set; }
public Int32 ErrorCode { get; private set; }
private ErrorValue(Int32 errorCode, String errorName)
{
if (_errors == null)
_errors = new Dictionary<int, ErrorValue>();
ErrorName = errorName;
ErrorCode = errorCode;
_errors.Add(errorCode, this);
}
public static IEnumerable<ErrorValue> Errors { get { return _errors.Values; } }
public static ErrorValue GetErrorByCode(Int32 errorCode)
{
return _errors[errorCode];
}
}
This will lead to a less error-prone code due to type safety, since you can write methods with paramters of type ErrorValue:
void HandleError(ErrorValue ev)
{
// bla bla
}
Another benefit is that with this approach, you can easily extend the type; e.g. add other properties like Description, without huge changes to your code.
If you need similar static global collections, you can extract a common generic base class to provide methods like GetById or GetByName or similar.
There should be no difference in the generated IL except the beforefieldinit flag.
I think the first one is simple if items are static/hard coded and not to be loaded from DB or some other data source.
Second one is using singleton pattern that is used heavily in applications where object is to be created only once and reuse that object reference throughout the life cycle of application. and offers to initialize collection from any other data sources.
Conclusion: both are good but depends on what you need. personally i like the second way as it follows a design pattern.
I'm currently storing a list of Tests with associated information, including database IDs, inside static variables in my code. Here's an example:
public static class IsokineticTests
{
// Cervical Spine Group
public static MyopathologyTest NeckFlexors = MyopathologyTest.Create(600, "Neck Flexors");
public static MyopathologyTest AnteriorObliques = MyopathologyTest.Create(601, "Anterior Obliques");
public static MyopathologyTest NeckExtensors = MyopathologyTest.Create(602, "Neck Extensors");
public static MyopathologyTest PosteriorObliques = MyopathologyTest.Create(603, "Posterior Obliques");
public static MyopathologyTest LateralFlexion = MyopathologyTest.Create(604, "Lateral Flexion");
// Shoulder Group
public static MyopathologyTest ShoulderAbductors = MyopathologyTest.Create(610, "Shoulder Abductors");
public static MyopathologyTest ShoulderExtensors = MyopathologyTest.Create(611, "Shoulder Extensors");
public static MyopathologyTest ShoulderFlexors = MyopathologyTest.Create(612, "Shoulder Flexors");
public static MyopathologyTest ShoulderLateralRotators = MyopathologyTest.Create(613, "Shoulder Lateral Rotators");
public static MyopathologyTest ShoulderMedialRotators = MyopathologyTest.Create(614, "Shoulder Medial Rotators");
}
These then get used to create a test group through other static properties get methods:
public static class IsokineticTestGroups
{
public static IsokineticTestGroup CervicalSpine
{
get
{
return IsokineticTestGroup.Create("Cervical Spine",
new List<MyopathologyTest>
{
IsokineticTests.NeckFlexors,
IsokineticTests.AnteriorObliques,
IsokineticTests.NeckExtensors,
IsokineticTests.PosteriorObliques,
IsokineticTests.LateralFlexion
});
}
}
}
The problem I'm having now is there is essentially no way to lookup the MyopathologyTest for a specific ID. One solution would be to create a dictionary and manually insert all these tests into the dictionary with the ID as the key. This seems like repeating a lot of code though.
What is the proper way to be implementing something like this? I'm thinking I need to externalize the test data, load in the tests during runtime and generate the proper look-up tables and groups on the fly. Is this the right approach I should be looking at or is there a better way?
Why not keep the test information in a database, like SQLite, and fetch the data on an as-needed basis using ADO.NET libraries? Response time is virtually instantaneous, so you have no need to store many test objects in a dictionary.