Feedback on automatic form filling with reflection Context:

I need to fill a handful of .docx templates with answers that come from form.responses, which is a dynamic object that comes from a JSON and can have different properties that vary according to the type of the form that was answered.

To do the filling, we need to instantiate a DTO called BindDto that takes the template string (eg.: ${PersonName}) and the value that will replace it (eg.: form.responses.client_name = "John Doe").

In my case, I created some [X]Constants classes that have properties that look like this...

public static readonly KeyValuePair&lt;string, string&gt; PERSON_NAME = new KeyValuePair&lt;string, string&gt;("client_name", "${PersonName}");
public static readonly KeyValuePair&lt;string, string&gt; PERSON_AGE = new KeyValuePair&lt;string, string&gt;("my_age", "${PersonAge}");
public static readonly KeyValuePair&lt;string, string&gt; MOTHER_NAME = new KeyValuePair&lt;string, string&gt;("mother", "${MotherName}");


...to map which template string each field from the JSON correponds to.

The code below was written so I could fill all the templates independent from which fields they might have by searching the [X]Constants classes and using the KeyValuePairs that I have set.

It works (o' course), but it seems I little... clumsy. And I don't have enough knowledge about C# to be sure this isn't pure madness.

What do you think about this code? Is it valid? Is is overengineering? How can I improve it?

I don't think performance will ever be a concern, but I would like to be enlightened in that sense too.

Thanks in advance to anyone willing to discuss it!

public List&lt;BindDto&gt; GenerateBinds(IEnumerable&lt;Form&gt; forms)
{
    var constants = new List&lt;FieldInfo&gt;();
    var binds = new List&lt;BindDto&gt;();

    constants.AddRange(typeof(AuthConsts).GetFields());
    constants.AddRange(typeof(ClientConsts).GetFields());
    constants.AddRange(typeof(ContactConsts).GetFields());
    constants.AddRange(typeof(AddressConsts).GetFields());
    constants.AddRange(typeof(ReferenceConsts).GetFields());

    foreach (var form in forms)
    {
        var formResponses = form.response.ToObject&lt;Dictionary&lt;string, string&gt;&gt;();

        IEnumerable&lt;string&gt; formFields = formResponses.Keys;

        foreach (var field in formFields)
        {
            foreach (var constant in constants)
            {
                if (constant.FieldType == typeof(KeyValuePair&lt;string, string&gt;))
                {
                    var templateString = (KeyValuePair&lt;string, string&gt;)constant.GetValue(this);

                    if (templateString.Key == field)
                        binds.Add(new BindDto(templateString.Value, formResponses[field]));
                }
            }
        }
    }

    return binds;
}
Just to tell you upfront, your code looks good, is easy to read and everything is well named. But it can be improved nevertheless.

First thing, public methods should always validate its method arguments. Passing null would lead to a nasty NullReferenceException at the start of the most outer foreach loop.  

I would suggest making the constants a class level variable being filled in the constructor, because the types won't usually change while your code is running.  

By restricting FieldType of the constants to KeyValuePair&lt;string, string&gt; will eliminate the if inside the most inner loop and will limit the constants to a smaller number.  

Omitting braces {} although they may be optional can be dangerous because it may lead to hidden and therfor hard to find bugs. I would like to encourage you to use them.

Implementing the mentioned points will look like this  

private readonly List&lt;FieldInfo&gt; constants = new List&lt;FieldInfo&gt;();
public ctor()
{
    constants.AddRange(typeof(AuthConsts).GetFields());
    constants.AddRange(typeof(ClientConsts).GetFields());
    constants.AddRange(typeof(ContactConsts).GetFields());
    constants.AddRange(typeof(AddressConsts).GetFields());
    constants.AddRange(typeof(ReferenceConsts).GetFields());
}

public List&lt;BindDto&gt; GenerateBinds(IEnumerable&lt;Form&gt; forms)
{
    if (forms == null) { throw new ArgumentNullException(nameof(forms)); }

    var neededType = typeof(KeyValuePair&lt;string, string&gt;);
    var binds = new List&lt;BindDto&gt;();
    var keyValueConstants = constants.Where(c =&gt; c.FieldType == neededType);

    foreach (var form in forms)
    {
        var formResponses = form.response.ToObject&lt;Dictionary&lt;string, string&gt;&gt;();

        IEnumerable&lt;string&gt; formFields = formResponses.Keys;

        foreach (var field in formFields)
        {
            foreach (var constant in keyValueConstants)
            {
                var templateString = (KeyValuePair&lt;string, string&gt;)constant.GetValue(this);

                if (templateString.Key == field)
                {
                    binds.Add(new BindDto(templateString.Value, formResponses[field]));
                }
            }
        }
    }

    return binds;
}