Reflection in C# to modify a private constant field in a class
I have the开发者_开发技巧 following class:
class RuleParser
{
private const String FILE = "./rules/DetectionStrategies.xml";
.
.
.
}
Now in my test project I want to set the FILE constant to another value. How can I achieve that using Reflection?
You fell into a trap...
const != readonly
If it was read-only, you could do that, but const
means compile-time constant, which compilers in turn embed into the resulting program. Hence what you do won't have an effect on pretty much any program, yours or others'.
Add this to your config file:
<appSettings>
<add key="DetectionStrategies" value="./rules/DetectionStrategies.xml" />
</appSettings>
But I would have it as a property with a private setter instead like such:
class RuleParser
{
private string _file = string.Empty;
private string File
{
get
{
if(string.IsNullOrEmpty(_file))
_file = ConfigurationManager.AppSettings["DetectionStrategies"];
return _file;
}
private set;
}
}
You need to remember to include the System.Configuration
.
EDIT: Since it has to be a compile time constant when you're assigning values to a const
I removed that and only kept the "property" with private set solution.
EDIT 2: The important part of this is that you should only use const
for true constants, configurable values should be configurable and a good place for that is the config file. Although, you don't have to use the config file, you could as well write your own configuration class that goes against a database instead or against a database with the configuration file as fallback. I might be thinking that you want to use a static
variable and not const
but that depends on how you're using the variable and in what context.
Instead of trying to change a const
in runtime, (or a readonly
or whatever), I'd suggest you consider to make some design changes to improve the testability of your code.
Some simple examples would be:
- Move the value to
App.Config
so that the test can have different values. - Abstract the file path from the
RuleParser
class by providing it in the constructor. Either by specifying the path itself, or by providing some interface (e.g.IFileParserConfig
) that would provide the value in runtime.
Geez dude, do you know what constant means? You can't change it. I think that compilers don't even compile references to constants, they just compile the actual value, so they wouldn't even notice if the value actually changed.
精彩评论