1

I have an object XMLLog that is retrieved from a database. A form allows a user to edit fields in the object, but because of convoluted reasons, I can't return the modified object, I'm returning a list of Keys in a Post.

I would like to do the following:

//get XMLLog from the database

foreach (var key in Request.Form.AllKeys)
{
    XMLLog.key = Request.Form[key];
}

//write XMLLog back to the Database

Is there any way to accomplish that without a giant case statement to test for each possible key?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
ItinerantEngineer
  • 255
  • 1
  • 4
  • 14
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jul 03 '13 at 23:06
  • Duplicate of [In C# How to dynamically specify a member of a object, like obj\["abc"\]](http://stackoverflow.com/questions/5716766/in-c-sharp-how-to-dynamically-specify-a-member-of-a-object-like-objabc-in-p) – Raymond Chen Jul 03 '13 at 23:54

2 Answers2

3

You can do this using reflection, but it would be very slow. Here's a small program that demonstrates the principal (you can compile and run it):

using System;
using System.Collections.Generic;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        var log = new XmlLog();
        var values = new Dictionary<string, string> { { "Hello", "1" }, { "World", "2" } };

        foreach (var methodInfo in typeof(XmlLog).GetProperties(BindingFlags.Instance | BindingFlags.Public))
        {
            methodInfo.SetValue(log, values[methodInfo.Name]);
        }

        Console.WriteLine(log.Hello);
        Console.WriteLine(log.World);
    }

    class XmlLog
    {
        public string Hello { get; set; }
        public string World { get; set; }
    }
}

This can be done faster by using code generation. You have several options like:

  1. Use Reflection over the XmlLog type and generate C# code that will be compiled along with your application.
  2. Use Reflection to build an Expression that sets XmlLog's properties, and then compile it into a Func or Action in runtime.
Ran
  • 5,989
  • 1
  • 24
  • 26
1

Reflection is how you would do this:

foreach (var key in Request.Form.AllKeys)
{
    var prop = typeof(XMLLog).GetProperty(key);
    prop.SetValue(myXmlLog, Request.Form[key], null);
}

This assumes a very simple structure with all strings - you may need to add validation, conversion, etc., depending on the data types and complexity of your XMLLog class.

This is not a great solution either. Ideally, you'd let the framework handle mapping form posts to an object, like with MVC. If you describe your environment a little more, maybe we can get a better answer.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136
  • I'd love to have it map directly but unfortunately the source of the XMLLog object uploads to the database as straight XML with up to five layers of nesting and the possibility that any element can be null. We tried creating a mess of models and Editor Templates which, frankly, was more confusing and error prone than a giant case switch with a form post of keys :) – ItinerantEngineer Jul 03 '13 at 23:49