Avoid Magic String Constants in C# Using Reflection


Magic string constants are as bad as magic numbers. They are error-prone. One bad impact is that if you have quite a number of usages throughout the project, you have to change them one by one (and may be likely to miss a few places) if somehow the values need to be modified.

To avoid that, we can use the Dynamic feature of .NET C#, the Reflection. Let’s see the code first.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Linq;
 
namespace HelloACM_ConsoleApplication_GetFields
{
    public static class Const
    {
        public static readonly string A = "a";
        public static readonly string B = "b";
 
        public static bool HasKey(string key)
        {
            var obj = typeof (Const);
            var fields = obj.GetFields();
            return fields.Any(field => field.Name == key);
        }
 
        public static string GetValue(string key)
        {
            var obj = typeof(Const);
            var fields = obj.GetFields();
            foreach (var fe in fields.Where(fe => fe.Name == key))
            {
                return fe.GetValue(obj).ToString();
            }
            return "";
        }
    }
 
    class Program
    {
        static void Main()
        {
            Console.WriteLine(Const.GetValue("A"));
            Console.WriteLine(Const.GetValue("B"));
            Console.WriteLine(Const.GetValue("C"));
        }
    }
}
using System;
using System.Linq;

namespace HelloACM_ConsoleApplication_GetFields
{
    public static class Const
    {
        public static readonly string A = "a";
        public static readonly string B = "b";

        public static bool HasKey(string key)
        {
            var obj = typeof (Const);
            var fields = obj.GetFields();
            return fields.Any(field => field.Name == key);
        }

        public static string GetValue(string key)
        {
            var obj = typeof(Const);
            var fields = obj.GetFields();
            foreach (var fe in fields.Where(fe => fe.Name == key))
            {
                return fe.GetValue(obj).ToString();
            }
            return "";
        }
    }

    class Program
    {
        static void Main()
        {
            Console.WriteLine(Const.GetValue("A"));
            Console.WriteLine(Const.GetValue("B"));
            Console.WriteLine(Const.GetValue("C"));
        }
    }
}

We have defined a static class Const to hold two constants (public attributes). So you can replace the code in your project where needed to Const.A and Const.B. In case you want to check if a field is defined, you can use the defined function HasKey which uses the Reflection technology.

Similarly, we can get the value of the fields dynamically. The GetValue illustrates this purpose.

We also use LINQ for a better code readability. If you don’t like to define “static” stuffs, you can rewrite the above example with some changes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Linq;
 
namespace HelloACM_ConsoleApplication_GetFields
{
    public class Const
    {
        public readonly string A = "a";
        public readonly string B = "b";
 
        public bool HasKey(string key)
        {
            var obj = GetType(); // instance
            var fields = obj.GetFields();
            return fields.Any(field => field.Name == key);
        }
 
        public string GetValue(string key)
        {
            var obj = GetType();  // instance
            var fields = obj.GetFields();
            foreach (var fe in fields.Where(fe => fe.Name == key))
            {
                return fe.GetValue(this).ToString();  // this instead of obj
            }
 
            return "";
        }
    }
 
 
    class Program
    {
        static void Main()
        {
            var obj = new Const();
            Console.WriteLine(obj.GetValue("A"));
            Console.WriteLine(obj.GetValue("B"));
            Console.WriteLine(obj.GetValue("C"));
        }
    }
}
using System;
using System.Linq;

namespace HelloACM_ConsoleApplication_GetFields
{
    public class Const
    {
        public readonly string A = "a";
        public readonly string B = "b";

        public bool HasKey(string key)
        {
            var obj = GetType(); // instance
            var fields = obj.GetFields();
            return fields.Any(field => field.Name == key);
        }

        public string GetValue(string key)
        {
            var obj = GetType();  // instance
            var fields = obj.GetFields();
            foreach (var fe in fields.Where(fe => fe.Name == key))
            {
                return fe.GetValue(this).ToString();  // this instead of obj
            }

            return "";
        }
    }


    class Program
    {
        static void Main()
        {
            var obj = new Const();
            Console.WriteLine(obj.GetValue("A"));
            Console.WriteLine(obj.GetValue("B"));
            Console.WriteLine(obj.GetValue("C"));
        }
    }
}

We use Object.GetType() method to get the instance instead of typeof (Class) for static classes (no instances). We use GetValue(this) instead of GetValue(obj) because in non-static classes, the instance is this.

One of the beauty of C# compared to C++ is its simplicity in the complex stuffs.

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
506 words
Last Post: Does TeamViewer Support Multi Screens (Monitors)?
Next Post: GUID for Random Unique ID (C#)

The Permanent URL is: Avoid Magic String Constants in C# Using Reflection

Leave a Reply