6

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?

4 Answers4

9

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'.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • 1
    Technically speaking, it's still possible to change it. Even though it's set by the compiler, you can locate the variable in the binary file and change it there. – Pedery Jan 01 '11 at 22:46
  • Yes... hence why I said "what you do won't have an effect on pretty much any program", not "this is impossible." Technically speaking, it *would* have an effect on a program if that program was compiled with a rather dumb compiler that didn't inline the value of the field... hence the "pretty much". :) – user541686 Jan 01 '11 at 22:47
3

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.

Tomas Jansson
  • 22,767
  • 13
  • 83
  • 137
  • Ehm, the nature of const is that it is 100% const. You can't assign it a value from anything else than a C# constant. – Dykam Jan 01 '11 at 21:52
  • @Dykam: I thought that was the case but not 100 %... I added a sentence about it. – Tomas Jansson Jan 01 '11 at 21:55
  • That's true, but I think his main problem is that he is not using the config file for parameters that should be configurable. If he decide to use a `readonly` or property doesn't matter to me. – Tomas Jansson Jan 01 '11 at 22:10
0

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:

  1. Move the value to App.Config so that the test can have different values.
  2. 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.
Ran
  • 5,989
  • 1
  • 24
  • 26
-2

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.

fejesjoco
  • 11,763
  • 3
  • 35
  • 65
  • 1
    I would have upvoted it if it was worded less lofty. Also, about reference types: http://stackoverflow.com/questions/1109805/declaring-a-const-double-in-c/1109849#1109849 – Dykam Jan 01 '11 at 21:50
  • Yes of course, you can't skip references to arrays. But I've seen many instances while browsing in Reflector that primitive constant values were used instead of field references. – fejesjoco Jan 01 '11 at 21:53
  • I think Dykam was also referring to the "Geez dude" bit. I know from your previous answers and comments that you have interesting knowledge and experience, why spoil it by being condescending? – Tim Lloyd Jan 01 '11 at 22:03
  • English is not my first language, I totally thought I was being funny :) – fejesjoco Jan 01 '11 at 22:55