HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Can my string to instance construction be improved?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
canimprovedconstructioninstancestring

Problem

I have a Dictionary (named tableDict) that has been parsed from JSON. The string describes the intended construction of a class T which is defined within the housing class of this code. The object is the numerical probability value that pairs up with the generated reference of T.

The string can be in either of two formats. Something encased in brackets, i.e. "(arg0, arg1, arg2, ...)", will call the constructor with these arguments. Anything else is assumed to be a name of a property of type T that returns a predefined T, i.e when T is of type Color, "Black" would lead to looking for Color.Black.

I managed to get something to work however I pieced this together from googling each problem I encountered. A lot of what I have used is new to me, it's highly likely I have gone about it in an inefficient roundabout fashion.

```
for (int i = 0; i kvp = tableDict.ElementAt(i);
string s = kvp.Key;

if (Regex.IsMatch(s, @"\(([^\)]+)\)", RegexOptions.None))
// Key is "( something )" - entry is constructor
{
string sCon = s.WhitespaceRemoved();
sCon = sCon.Substring(1, sCon.Length - 2); // Remove brackets

string[] argsAsStrings = sCon.Split(',');
object[] args = argsAsStrings.Select(num => (object)int.Parse(num)).ToArray();
// I have only implemented this for the Color class.
// I assume the constructor is comprised of ints.

T item = (T)Activator.CreateInstance(typeof(T), args);
double prob = Convert.ToDouble(kvp.Value);

var entry = new RawChanceTableEntry(item, prob);

list.Add(entry);
}
else // Parse string as a property of T instead
{
string sProp = s;
Type type = typeof(T);
PropertyInfo propInfo = type.GetProperty(sProp);

object obj = Activator.CreateInstance(type);

T item = (T)propInfo.GetValue(obj, null);
double prob = Convert.ToDouble(kvp.Value);

var entry = ne

Solution

I'd compact the main loop as such:

for (var i = 0; i  (object)int.Parse(num)).ToArray();

                // I have only implemented this for the Color class.
                // I assume the constructor is comprised of ints.
                list.Add(new RawChanceTableEntry(
                    (T)Activator.CreateInstance(typeof(T), args),
                    Convert.ToDouble(kvp.Value)));
            }
            else
            {
                // Parse string as a property of T instead
                var type = typeof(T);

                list.Add(new RawChanceTableEntry(
                    (T)type.GetProperty(s).GetValue(Activator.CreateInstance(type), null),
                    Convert.ToDouble(kvp.Value)));
            }
        }


I also create a specific RegEx for the bracket matching that should be faster as it's compiled at the class level:

private static readonly Regex brackets = new Regex(@"\(([^\)]+)\)", RegexOptions.Compiled);

Code Snippets

for (var i = 0; i < tableDict.Count; i++)
        {
            var kvp = tableDict.ElementAt(i);
            var s = kvp.Key;

            // Key is "( something )" - entry is constructor
            if (brackets.IsMatch(s))
            {
                var constructor = s.WhitespaceRemoved();

                constructor = constructor.Substring(1, constructor.Length - 2); // Remove brackets

                var argsAsStrings = constructor.Split(',');
                var args = argsAsStrings.Select(num => (object)int.Parse(num)).ToArray();

                // I have only implemented this for the Color class.
                // I assume the constructor is comprised of ints.
                list.Add(new RawChanceTableEntry<T>(
                    (T)Activator.CreateInstance(typeof(T), args),
                    Convert.ToDouble(kvp.Value)));
            }
            else
            {
                // Parse string as a property of T instead
                var type = typeof(T);

                list.Add(new RawChanceTableEntry<T>(
                    (T)type.GetProperty(s).GetValue(Activator.CreateInstance(type), null),
                    Convert.ToDouble(kvp.Value)));
            }
        }
private static readonly Regex brackets = new Regex(@"\(([^\)]+)\)", RegexOptions.Compiled);

Context

StackExchange Code Review Q#38536, answer score: 4

Revisions (0)

No revisions yet.