Преобразование строки в динамический объект

Есть ли простой способ преобразования:

string str = "a=1,b=2,c=3";

в

dynamic d = new { a = 1, b = 2, c = 3 };

Я думаю, что, возможно, я мог бы написать функцию, которая разбивает строку и обрабатывает результаты для создания динамического объекта. Мне просто интересно, был ли более элегантный способ сделать это.

Ответ 1

Вы можете использовать Microsoft Roslyn (здесь все -in-one пакет NuGet):

class Program
{
    static void Main(string[] args)
    {
        string str = "a=1,b=2,c=3,d=\"4=four\"";
        string script = String.Format("new {{ {0} }}",str);
        var engine = new ScriptEngine();
        dynamic d = engine.CreateSession().Execute(script);
    }
}

И если вы хотите добавить еще более сложные типы:

string str = "a=1,b=2,c=3,d=\"4=four\",e=Guid.NewGuid()";
...
engine.AddReference(typeof(System.Guid).Assembly);
engine.ImportNamespace("System");
...
dynamic d = engine.CreateSession().Execute(script);

Исходя из вопроса в вашем комментарии, есть уязвимости для инъекций кода. Добавьте ссылку System и пространство имен, как показано выше, а затем замените str на:

string str =
    @" a=1, oops = (new Func<int>(() => { 
                Console.WriteLine(
                    ""Security incident!!! User {0}\\{1} exposed "",
                    Environment.UserDomainName,
                    Environment.UserName); 
                return 1; 
            })).Invoke() ";

Ответ 2

Я думаю, что если вы преобразуете "=" в ":" и обернете все фигурными скобками, вы получите действительную строку JSON.

Затем вы можете использовать JSON.NET для десериализации его в динамический объект:

dynamic d = JsonConvert.DeserializeObject<dynamic>(jsonString);

Вы получите то, что хотите.

Ответ 3

Вопрос, который вы описали, является чем-то вроде десериализации, т.е. конструирования объектов из формы данных (например, строки, байтового массива, потока и т.д.). Надеюсь, эта ссылка поможет: http://msdn.microsoft.com/en-us/library/vstudio/ms233843.aspx

Ответ 4

Вот решение, использующее ExpandoObject, чтобы сохранить его после его разбора. Сейчас он добавляет все значения как string s, но вы можете добавить некоторый синтаксический анализ, чтобы попытаться превратить его в double, int или long (вы, вероятно, захотите попробовать в этом порядке).

static dynamic Parse(string str)
{
    IDictionary<String, Object> obj = new ExpandoObject();
    foreach (var assignment in str.Split(','))
    {
        var sections = assignment.Split('=');
        obj.Add(sections[0], sections[1]);
    }
    return obj;
}

Используйте его как:

dynamic d = Parse("a=1,b=2,c=3");
// d.a is "1"