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.
Related
My question is: Can I define a static method "meth1" in a static class "classB" that, when called from "classA", searches for a specific field (in "classA", not in the class in which is defined)?
I try to explain better: I need to do something like this:
public class classA
{
string someText;
int anInt;
bool trueOrFalse;
public classA()
{
...
...
var variable = classB.meth1("variableName");
...
...
}
}
public static classB
{
public static object meth1(string name)
{
...
... //use "name" to find the variable with that name in the class from which "meth1" is called.
...
}
}
That because I have to read a backup of "last run values" of variables contained in a .txt file, written line by line as "variable name = value".
So I read the .txt, create an hashtable "backupHashtable" which contains ("variable name";"value"), and then I want to search variables by string "variable name" and reset them to "value".
If someone of you knows a better procedure I'm listening. Maybe the use of a Dictionary?
Thank you!
UPDATING
Ok, now I have a clearer idea of what I want to do: I want to implement a class "ClassB", separate from my main class "classA". In this new class I would have a "meth1" method which, running in a separate thread, saves every 10 seconds (for example) the state of some variables belonging to "classA". To communicate the "meth1" what are the variables that he has to save, I want to use a list containing the names (in the format "string", that's what I thought, but I guess it's not the only way) of these variables.
If you're wondering why I want to do this in a separate thread the answer is this: my application performs some recognition operation of some objects in live stream images from multiple cameras and then ancillary operations must be isolated as much as possible from the main code to increase the speed of execution.
Now, perhaps, it is more understandable what I said before.
Yes, but you also need to pass a reference to the instance of A. Then use reflection to get or set the property.
public static void Meth1(object obj, string propertyName)
{
var prop = obj.GetType().GetProperty(propertyName);
var value = prop.GetValue(obj);
...
}
If I were to get values from a textfile into a class, I think I'd load them in a dictionary first, and then set all properties one by one. (Maybe unless there are, say, hundreds of properties). When using reflection, there is a chance that the textfile contains the name of a property you don't want to be changed from outside.
object value;
if (dict.TryGetValue("someProperty", out value)) { a.SomeProperty = value; }
Please feel free to modify the title, I couldn't come up with any better one =\
Given the following example class
public class Person
{
public string Name;
public int ID;
public string City;
}
I need to create another mirror class, where every field is actually a wrapper of the original class:
public class PersonMirror
{
public FieldWrapper<string> Name;
public FieldWrapper<int> ID;
public FieldWrapper<string> City;
}
public class FieldWrapper<T>
{
public T Value;
public bool someBool;
public int someCounter;
// ..whatever
}
The thing is, I have many classes to mirror, and some of them have many fields! Moreover, the original class may be changed from time to time (add / remove / rename field), and every change must be applied to the mirrored class - not a good practice for maintainability.
My question is - is there a type safe way automate the decleration (rather then creation, such as generated code) of such mirrored classes?
EDIT:
Let's start from the beginning. In our SOA system, there is a resource access service (serviceX) responsible for updating items in the DB. Other services send it the modifications they would like to perform - in json that would be something like: {ID: 123, name : "myNewName"}. serviceX would then build an update query to send to the DB. However, there is a requirement that serviceX will expose a POCO interface, so that the interface will be language independent, so expressions such as (p=> p.name, "MyNewName") are not allowed. Another requirement is type safety, so json is not allowed either. Currently, the above solution is the best one we came up to answer all the requirements. Any better solutions are more then welcome!
IMO, there's no way to do what you want, except code generation.
Approaches for code generation could differ (this maybe source code generation + compilation, emitting IL code, either your own or existing one), but this is the only way.
use T4 to autogenerate your "WrapperClass".
Below, a proposition of how you could implement your FieldWrapper.
public class FieldWrapper<T, O>
{
private T _item;
private O _owner;
private PropertyInfo _setter;
public T Value
{
get { return _item; }
set {
if (!EqualityComparer<T>.Default.Equal(_item, value))
{
_item = value;
// do some personal check
_setter.SetValue(_owner, value);
}
}
}
public bool someBool;
public int someCounter;
// ..whatever
// CTOR
public FieldWrapper(O owner, Expression<Func<T, O>> propertyExpressionInTheOwner)
{
_owner = owner;
propertyName = (propertyExpressionInTheOwner.body as MemberExpression).Member.Name;
// get PropertyInfo using the owner and propertyName
}
}
Using the expression behavior permits you to create your fieldWrapper this way.
var p = new Person();
new FieldWrapper(p, (pers) => pers.Name);
The good point with this technique it is that if you person class change you will directly receive a compilation error.
With T4 the must is to load the assembly where all you class are, tag you class model with a specific attribute. Look into the assembly to found every class that have this attribute and generate the wrapper class associate.
You would have to run it after every code change, but you could create a code parsing application.
List desired keywords to substitute, such as " string ", " int ". Read the file, line by line. Find definition of classes (line contains "class"), then replace every instance of any given keyword in it with:
"FieldWrapper<" + keyword + ">"
You might want to drop keyword substitution inside methods (and perhaps in the method signatures / return types themselves) of by checking for "(" and ")", and the opening curly brace. Resume operation when you reach the closing curly brace. You can achieve that by storing the nesting level in an integer, incrementing it when hitting '{' and decrementing it when reaching '}'.
I've a small problem. I've a application monitoring part in a framework which is used by multiple applications.
Right now I've a functionality like this:
public enum Vars
{
CPU,
RAM
}
public void Add(Vars variable, object value)
{
[...]
}
The Variable which is used as Parameter in the Add method will be used as the name of the entry in the database.
Now I got the requirement, that applications can specify own variables outside the framework. Because you can't inherit from an enum this causes some trouble.
I see basicly 2 possibilities (which are bot not very satisfying in my opinion) to solve this.
Possibility 1:
public void Add(enum variable, object value)
This method would accept all sorts of enums, so users could use the Vars enums as well as enums which they've defined by themself. The problem with this solution: It would be possible, that users use the same names in both.. application and framework. I'm not able to differ between two enums with the value "CPU" (Framework may store percent values as "CPU", application may store process cpu usage as "CPU").
Possibility 2:
The second method would be an class instead a enum, something like:
public class Vars
{
public const string CPU = "CPU";
public const string RAM = "RAM";
}
The drawbacks here:
1. More to write.
2. I would have to define parameters as strings:
public void Add(string variable, object value);
This could lead to missuse as well (Applications which add strings directly instead defining a class which inherits from Vars).
Any thoughts on how to define a model which:
Can be inherited (to extend the values by applicationspecific values)
Can be used as a parameter
Ensures, that there are no double (=same value) entries
?
The context is not completely clear, but what about creating a class
public class Vars
{
public static Vars CPU = Vars.Get("CPU", 1);
public static Vars RAM = Vars.Get("RAM", 2);
//You can keep one of the params, name or id
private Vars(string name, int id)
{
...
}
public static Vars Get(string name, int id)
{
//check if id or name exists in static dictionary, and return that instance or create new one
}
}
public void Add(Vars variable, object value);
Now user can create any kind of Parameter and pass to the method,
Vars newVar = Vars.Get("MyNewParam", 10);
You can easily check if the passed param is one, about which you know
Get method returns same instance if the params are the same
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.
selenium = new DefaultSelenium(
ConfigurationManager.AppSettings["TestMachine"].ToString(),
4444,
ConfigurationManager.AppSettings["Browser"].ToString(),
ConfigurationManager.AppSettings["URL"].ToString()
);
Is there an efficient way to do this, instead of repeating:
ConfigurationManager.AppSettings[""].ToString()
I think a better idea is to write a wrapper class to everything that deals with configuration, especially if you write tests. A simple example might be:
public interface IConfigurationService
{
string GetValue(string key);
}
This approach will allow you to mock your configuration when you need it and reduce complexity
So you could proceed with:
public void SelTest(IConfigurationService config)
{
var selenium = new DefaultSelenium(config.GetValue("TestMachine"),
4444, config.GetValue("Browser"), config.GetValue("URL"));
}
or you could inherit your configuration from a List and reduce the typing to:
config["Browser"]
Yes, you can do
ConfigurationManager.AppSettings[""]
As it is already a string.
If you're using ConfigurationManager.AppSettings["Something"] at multiple places, you should create a static Config class, that reads your AppSettings via static properties.
You can go to the properties of the project and add Settings, then read it with:
Properties.Settings.Default.Property
I always create a config class per application which wraps access to the app/web.config file and exposes the config entries as properties. E.g. something like this:
public static class MyConfig
{
/// documentation of config entry
public static string Browser
{
get { return Read("Browser", "some default value"); }
}
/// documentation of config entry
public static int Port
{
get { return int.Parse(Read("Browser", "80")); }
}
public static string Read(string entry, string defaultValue)
{
var entry = ConfigurationManager.AppSettings[entry];
return string.IsNullOrEmpty(entry) ? defaultValue : entry;
}
}
This has several advantages:
I can define default values (e.g. if a config entry is optional/missing)
I can expose numerical/boolean config entries in the correct type (int, bool)
I can document all config entries in a central place
If you want have strong type reference, you can inherit from ConfigurationSection / ConfigurationElementCollection and ConfigurationElement.
You can specify default value to ConfigurationElement with [ConfigurationProperty("key", IsRequired = true, DefaultValue = "*^%)(#")] and validator like [StringValidator(MinLength = 3)] etc.
Write a helper function to get the parameter. You need to check if the key is actually present in the first place for good coding practices.
The only "more efficient" manner to pull from a config file is to consume the entire section and then iterate through what you desire. As you end up with looping code, it is unlikely to be more efficient than the method you have now.
One pattern to use to simplify is to create an "App settings" Singleton and load at Application Load. You essentially create a generic hashtable (dictionary, etc.) of string, string, so you can accomplish lookups more easily. But there is still the overhead of ripping through the app settings section.
You need to be a bit more creative with the class name perhaps but you could do something along the lines of:
class ConfigManager
{
public static string GetSetting(string name)
{
return ConfigurationManager.AppSettings[name].ToString();
}
}