问题
I've been agaonizing about this problem for some days: I have a class Info
public class Info
{
private int _no;
public int No
{
get
{
return _no;
}
set
{
_no = value;
}
}
}
That class can be used anywhere in any classes (inherited or as property). The property can be considered as security relevant or not. That information is known at design time and needs to be stored for that particular property.
So for some classes which uses that class as property I want the member "No" to be set accordingly.
public class IsRelevant
{
private Info _prop = new Info();
public Info Prop { get { return _prop; } set { _prop = value; } }
}
public class IsNotRelevant
{
private Info _prop = new Info();
public Info Prop { get { return _prop; } set { _prop = value; } }
}
For a first try I was thinking about introducing an custom attribute like this:
[SecurityRelevant(RelevantLevel = SecurityRelevant.SecurityRelevant_Level1, IsRelevant = true)]
And then once I instanciate the class "IsRelevant", I will go through the properties and its classes and set the custom attribute as desired:
IsRelevant.Prop.No => IsRelevant = true, eg IsNotRelevant.Prop.No => IsRelevant=false.
But as far as I understood the meta information (attributes) for a class is an instance created once for each type. So if I change the values of the custom attribute I will change it for all instances of that class (because it's bound to that type!?)
Edit: This can't be done as stated here: Change Attribute's parameter at runtime Everytime you access the custom attributes, a new instance with the default values will be created. Changes to that attribute won't be stored there.
A second approach was to store that information in an external class and save all the model paths etc. I don't like that because the information belongs to a specific class.
The third approach was to implement an interface which holds a dictionary which stores that information:
public interface ISecRelevant
{
Dictionary<PropertyInfo, bool> SecInfo { get; set; }
}
and then every class which has a security relevant property would need to implement it. On every instantiation of that class, the information needs to be added in the dicationary. This is the best solution I came up with yet. The class which holds the information doesn't necessarily needs to be a dictionary because in a second step I want to ask an instance with a potential security relevant property if it really is relevant. So I could just pass that property in a method of that "security relevant information container" and ask if the property is relevant.
So I'm basically asking if someone has a better idea to store that information or to access it, because somehow I still don't like the solution.
So here are some general conclusions about that problem:
- The information whether a property is security relevant is not really a runtime information, but available upfront. So ideally I would like to store it in a "static" way
- The information is best to be attached to the property, at least to the parent class, because only it should know about that information, not any other class which uses that Info class to avoid coupling
- There are many more security relevant properties which are scatterd over a lot more classes. These are also used in a more deeper and complex object hierarchy, but I thought it basically comes down to the problem I described here.
Edit: Since I did not come up with a better idea, I implemented the third solution, but with a string for the property name. But then I stumbled into another problem when using Lists. What happens if you have a List as property with a type that has a sec-relevant property? The List would have to know where it is sitting to enable adding the information to every instance which is inserted in the List...
While searching I found another post, basicallay asks for the same thing: C# - add some meta data associated to a particular field when I am assigning a value to the field of a class? He suggests to implement a base class which hold that kind of information. This will work for "normal" properties. But not for the list-case.
Further explanation and example:
I thought the example with "security relevant" was helping you guys to understand the problem, but maybe it just confused you. Simply said: I need to attach meta information a any property of a class (and also to the items which are maybe contained in a list). Where I need to put this information is known at design-time but is dependent on the instanciation of the classes. So it DOES matter who is instanciating the class. This is also the reason why I cant use static information. Here is an example:
Class A {
public int MetaProperty; // (this it the propert where i might want to add meta info)
}
Class B {
public A ThePropertyWithMetadata;
}
Class C{
public A TheProperty;
}
Whenever I create an instance of class B, I need to attach meta information to
InstanceOfB.ThePropertyWithMetadata.MetaProperty
On the other hand whenever I create an instance of class C, I DO NOT want to to attach any meta information to that property. I want to show that meta info in the user interface and give the user more information about that property. So I do know when to assign the meta information, but cant put it in the classes at design time. Hope this clarifies it now :-)
来源:https://stackoverflow.com/questions/12407173/storing-meta-information-to-class-properties