Having the same class work as a Property Bag and a series of Properties
My C# class works as a holder for a bunch of values, which now are stored as properties. In a move to increase extensibility I'm going to add a Dictionary to it, so that people can store whatever properties they want in there, without having to change the class code. However I would like to keep backwards compatibility, by allowing the old properties to still be accessed eit开发者_JS百科her through the bag accessor or the the original getter setter. I.e. I want the following two pieces of codes to have the same effect.
properties.Config1 = value
properties["Config1"] = value
Does anyone have any tips on best practices for such a change? One complication is that some existing getter setter have validation/logic in them.
If you want to preserve backwards compatibility, you can't expose the Dictionary directly. Instead, you can implement an indexer on your class and put some checks within it to ensure that the appropriate logic is run when one of the existing properties is accessed using that syntax.
If you do it with an indexer, you have the option of putting the existing properties into the Dictionary, or just leaving them as is and calling their existing getters and setters from the indexer's getter/setter when the appropriate string is passed as a key.
The indexer might look something like this:
public object this[string key] {
get {
if (key == "Config1") return this.Config1;
else return propBag[key];
}
set {
if (key == "Config1") this.Config1 = value;
else propBag[key] = value;
}
}
Of course, you might want to add checks to ensure the key exists in the else
block, but this should get you started.
One more thing to consider: changing this class to add property bag behavior, whether implemented as a public dictionary or indexer, will cause the class's interface to change. So, you won't have to rewrite existing code, but you will have to recompile it once you change the class.
Use ExpandoObject
which is in fact a dictionary of string/object with a syntactic sugar:
http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
Have properties
as an ExpandoObject
. Here is the sample from MSDN:
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<String, Object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33
Wouldn't you just replace your references to the internal fields '_config1' to point to the dictionary store instead? You'd need to implement some logic to check if the dictionary key exists etc. but it shouldn't be that monumental of a change.
I'm looking to implement something similar to this myself, and both backwards and forwards compatibility are issues.
I'm looking to use reflection within my property bag to check if the base class implements that property explicitly, and if it does, have the Property Bag refer to the base implementation instead.
For example, if my class implements:
string MyClass.Name
Then internally the property bag will use reflection to forward requests of MyClass.Properties["Name"]
to MyClass.Name
This can cause a problem. If users of my class have, for example, set up an ad-hoc property list(of string) MyClass.Properties["Address"]
, and then I implement a default property string Myclass.Address
- this will obviously cause the users code to break.
This isn't an issue for the environment I'm developing in though.
Below is a pretty good article regarding some aspects of code design for anyone who wants to make a "PropertyBag"-type class, and who doesn't want the overhead of System.Dynamic
http://www.codeproject.com/Articles/12282/Implementing-a-PropertyBag-in-C
精彩评论