I've got a Global Resource file with many values
Currently in code I call the value like this
TxtSuccess.Text = (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
But if later in the design we needed to rename variables then maintaining will be a pain.
would it be better to do something like this?
public class AppGlobalConstants
{
public string MsgSuccess{ get; private set; }
public AppGlobalConstants()
{
MsgSuccess= (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
}
}
Then if later on the team wanted to change the name of some of these global resources they could do so without having to modify any pages which used these resources.
We want to use globals as there are plans for our web application (asp.net web forms 4.5) to be available to additional countries and languages in the future.
I would rather do something like this:
public static class AppGlobalConstants
{
public static string MsgSuccess
{
get
{
return (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
}
}
}
This way, the values are static. In case the name changes, you simply modify the strings in this class. Because everything is static in this class, you could do something like this:
Console.WriteLine(AppGlobalConstants.MsgSuccess);
If you want, you could also add a set accessor to the properties. Because everything is static, there's no need to create instances of this class.
Related
I am writing an audiobook app in C# .NET Framework. I need to store on user disc information about audiobooks' locations and last listened audiobooks. I'm looking for the simplest and the most elegant way to do it. As easy as it can be.
What is the best (safe and proper) way to do it? How you would do it?
A very simple way is to create a custom class that holds properties for each setting you want to persist between sessions. Then create an instance of this class and set the properties with the values you want to persist.
Finally serialize the instance with a Json library transforming it in a string and save it to a location where you have read/write permissions.
To retrieve the information just do the reverse, read from the file, deserialize the string into an instance of your setting class and then use it.
So supposing a class like this:
public class ApplicationSettings
{
public string LastBookName { get; set; }
public List<string> PreviousTitles { get; set; }
}
You can have two helper methods like these one (making use of NewtonSoft.Json library NuGet here)
public void SaveSettings(ApplicationSettings aps)
{
string json = JsonConvert.SerializeObject(aps);
File.WriteAllText(#"E:\temp\savedsettings.json", json);
}
public ApplicationSettings LoadSettings()
{
string json = File.ReadAllText(#"E:\temp\savedsettings.json");
return JsonConvert.DeserializeObject<ApplicationSettings>(json);
}
Now you just need to call these two methods in the appropriate points of your code.
New to C#, and I understand that encapsulation is just a way of "protecting data". But I am still unclear. I thought that the point of get and set accessors were to add tests within those methods to check to see if parameters meet certain criteria, before allowing an external function to get and set anything, like this:
private string myName;
public string MyName;// this is a property, speical to c#, which sets the backing field.
private string myName = "mary";// the backing field.
public string MyName // this is a property, which sets/gets the backing field.
{
get
{
return myName;
}
set
{
if (value != "Silly Woman"){
myName = value;
}
}
}
But I've been seeing code in c# which just looks like this:
public string MyName { get; set; }
Why would you just have a get and set with nothing in there, - isn't that the same as just declaring your private backing field public? If you can just get and set it from outside, why wouldn't you just do it directly?
Indeed, creating an auto-property as follows:
public string Name { get; set; }
is identical to building a property backed by a field:
private string _name;
public string Name {
get { return _name; }
set { _name = value; }
}
The point of these properties is not to hide data. As you observed, they don't do this. Instead, these properties can do other stuff instead of just working with a field:
public string Name {
get { return _name; }
set { if (value == null) throw new Exception("GTFO!"); _name = value; }
}
Another thing is, you can make properties virtual:
public virtual string Name { get; set; }
which, if overridden, can provide different results and behaviours in a derived class.
By using public string MyName { get; set; }, you leave an ability to change its logic later without the need to recompile/change other code that uses your property.
For example, if you are making a library and v1 uses a field and v2 uses a property, applications that work with v1 will not work with v2 without recompilation (and, potentially, code changes if they are written in some .NET language that has different syntax for accessing fields).
Another important difference is in serialization scenarios -- a lot of them do not support fields. Also any interface that requires a property can not be implemented without using one, but depending on interface it may not be required to do any additional checks/logic in it.
It makes it easier to add logic later. If you have a class that has a public field that you want to change to a property, you have to recompile everything that uses your class. That's a key point that I didn't understand initially.
If you have a class:
public class MyClass
{
public string MyString;
}
You could access the value like this:
var myClass = new MyClass();
string s = myClass.MyString;
Now change that to a property:
public class MyClass
{
public string MyString { get; set; }
}
How is it accessed? The exact same way:
var myClass = new MyClass();
string s = myClass.MyString;
So no big deal, right? Well, actually....
Properties are actually compiled into getter and setter methods:
get_MyString() and set_MyString(string value)
So the two methods do produce different compiled code. Now if all your code that uses this class is in the same project, is not as big a deal, because it will all be compiled together. But if you have an API library that you've distributed, it can be a much bigger deal to update.
Because it is easier to change the Code if you want to add the checks/tests later on.
Especially if you have many inheritance and many classes in your code it is very hard to change the implementation from a public variable to a public Property.
Moreover you can add to the get and set within the property different attributes, e.g. if you are using reflection. The get and set of the property are internally different methods. If you have just a public variable /field it is not possible to added different properties to the different access ways.
Yeah, but you can easily change it to:
public string MyName { get; private set; }
Plus, properties are used in other scenarios, like DataContracts and Serialization... so, this is a nice feature... (Mostly, syntactic sugar. I think) EDIT: I take that back.. you can apply virtual to it, so it's not the same
Is it possible to have a resource file with entries that have multiple values.
Eg. Id like to have something like.
Resource.CanViewSection.Value
Resource.CanViewSection.Description.
My reason for this is that our database is being created with the code first approach, and we're going to need to implement very granular permissions in our application, so i'm expecting a lot of permissions & or possible repetition of items, and id like to centralize them all.
Thus in our database seeder i can do something like this:
private IEnumerable<Permission> SetupParameterPermissions()
{
var innerCollection = new List<Permission>
{
//id like to do this
this.New(Resource.CanViewSection.Value, Resource.CanViewSection.Description),
//instead of this
this.New("CanViewSection", "User can view the section")
};
return this.SetGroupId(innerCollection, PermissionGroupEnum.Parameters);
}
and in our services we can just run our access checks against the resource as well like this:
eg.
if(UserHasAccessTo(Resource.CanViewSection.Value))
{
// do something amazing
}
I've tried a few approaches, EG. adding a name to the value column of the resource & a description to the comment section, but i don't know how to programatically access the comments column of the resource file.
I realize I can achieve this effect with ENUMS as well, but i'm second guessing what the best approach would be, as we'll have a ton of permissions, and somehow the idea of a gigantic ENUM with 2 equally gigantic extensions weirds me out.
public enum SomeEnum
{
CanViewSection
}
public static class SomeEnumExtensions
{
public static string GetValue(this SomeEnum)
{
switch (me)
{
case SomeEnum.CanViewSection:
return "CanViewSection";
default:
return "Fail!";
}
}
public static string GetDescription(this SomeEnum)
{
switch (me)
{
case SomeEnum.CanViewSection:
return "YOLO!";
default:
return "Fail!";
}
}
}
I'm open to other suggestions as well?
Maybe you can try this (or something like it):
1) Create resource file with your ID's. F.e.
Resource.Code1
Resource.Code2
2) Create XML file and add it to project. It will look probably like this:
<codes>
<Code1 Value="Some value text" Description="Some description">
<Code2 Value="Some value text" Description="Some description">
</codes>
3) Create some kind of wrapper class with 2 fields - Value and Description, f.e.
public class ResourceWrapper
{
public string Value {get;set;}
public string Description{get;set;}
}
3) Then create simple static method which will get value from XML file by code from your resource file, parse it, and return ResourceWrapper as a result.
public static class ResourceHelper
{
public static ResourceWrapper GetSomeWrapper(string resourceCode);
}
Calling will look like (in your case):
ResourceWrapper wrap = ResourceHelper.GetSomeWrapper(Resource.Code1.ToString());
this.Add(new Permission(wrap.Value, wrap.Description));
Probably you would like to store a collection of already wrapped objects in some kind of cache, or else.
I'm trying to refactor some code that is passing different combinations of parameters depending on the type of configuration an object needs. For example:
public MyWidget(string server, string port)
{
...
}
public MyWidget(string server)
{
...
}
public MyWidget(bool createAThing,
string nameOfThingToBeCreated,
string server,
string port)
{
...
}
public MyWidget(bool createAThing, string nameOfThingToBeCreated)
{
...
}
...etc
I don't want to use properties, because it feels like it's hiding some possible dependencies e.g. the object might require the server to be passed in if there's the port property has been assigned. Don't get hung up on the example params, this is just something I'm pulling out of the air.
I looked at the Builder pattern, but it's not quite what I need. Any suggestions would be great!
I'm using .NET 2.0
You could use a configuration object and pass that to your constructor.
Something like this:
public class WidgetOptions
{
public string Server { get; set; }
public string Port { get; set; }
...
}
public class MyWidget
{
public MyWidget(WidgetOptions options)
{
Server = options.Server;
Port = options.Port;
...
}
}
Actually, if the intent is to always create a "valid" object such that the object is not ever in a half-configured state, then the Builder pattern is appropriate. The builder holds the data points until they are all assigned and can then create a completely configured object in one go.
But it sounds like you don't trust your developers to read the documentation to know what to configure...you do provide documentation, right ;)
In that case, perhaps provide a set of builders that each only exposes the properties that relate to the "mode" your final object needs.
So something like this (pseudo code and made up, since you didn't provide any hinst about what you are really trying to model)
WidgetBuilder
+ whatever properties are common to all widget creation
+ MakeWidget
VectorWidgetBuilder : WidgetBuilder
+ get/set Lines
+ MakeWidget
BitmapWidgetBuilder : WidgetBuilder
+ get/set Image
+ MakeWidget
AnimatedWidgetBuilder : WidgetBuilder
+ get/set Images
+ get/set FrameRate
+ MakeWidget
A variation of this would be to define these permutations as various WidgetOptions, as Master Morality called them, but each distint set of options is its own class. So you might have VectorWidgetOptions, BitmapWidgetOptions, and AnimatedWidgetOptions that just exposes the related set of properties.
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.
ConstructorInfo constructor = typeof(Settings).GetConstructor(BindingFlags.Static | BindingFlags.NonPublic,null, new Type[0], null);
constructor.Invoke(null, null);
You could use reflection:
var prop = typeof(Settings).GetField("setting1", BindingFlags.Static |
BindingFlags.Public);
prop.SetValue(null, "Bar");
string currentValue = Settings.setting1; //Bar
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
The only option comes to my mind which is requires a lot of work:
Create another AppDomain
Load assembly in the other domain
Use Remoting to get the data
If settings changed, unload the AppDomain and do steps 1 to 3 again
I would use reflection
var info = typeof(Settings)
.GetField("Settings",BindingFlags.Static|BindingFlags.Public);
info.SetValue(null, "setting4");
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);
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
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.
Change your values to properties:
public static class Settings
{
public static setting1
{
get { return SettingmanagerClass.GetSetting("setting1"); }
}
public static setting2
{
get { return SettingmanagerClass.GetSetting("setting2");
}
public static setting3
{
get { return SettingmanagerClass.GetSetting("setting3");
}
}
Also, this does not change the signature of your code.