2013-07-17 18 views
10

Czy istnieje prosty sposób na konwersję:Konwersja String na obiekt dynamiczny

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

do:

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

myślę, że prawdopodobnie może napisać funkcję, która dzieli ciąg i pętle wyniki stworzyć obiekt dynamiczny. Zastanawiałem się, czy istnieje bardziej elegancki sposób robienia tego.

+0

Czego oczekujesz wartości być? Zawsze 'int'? –

+0

@SimonL Nie, wartości mogą być dowolnym typem danych. – Coltech

+0

Kiedy mówisz: _any_, czy to też może być klasa? Lub po prostu typy proste ('string's, typy liczbowe) –

Odpowiedz

6

Można użyć Microsoft Roslyn (here „s all-in-one pakiet 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); 
    } 
} 

A jeśli chcesz dodać jeszcze bardziej złożone typy:

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); 

opiera się na pytanie w komentarzu, są luki w zabezpieczeniach kodu. Dodaj odwołanie System i nazw, jak pokazano tuż powyżej, następnie wymień str z:

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

To jest całkiem interesujące. Zastanawiam się, czy to otwiera podatność na wstrzykiwanie kodu? Jak ucieczka przed ciągiem i wykonywanie losowego kodu podobnego do wtrysku sql? – Coltech

7

Myślę, że jeśli skonwertujesz "=" na ":" i zawiniesz wszystko za pomocą nawiasów klamrowych, otrzymasz prawidłowy ciąg JSON.

Następnie można użyć Json.NET deserializować go do dynamicznego obiektu:

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

Dostaniesz to, co chcesz.

+1

Co jeśli łańcuch zawiera' = ' –

+0

Myślę, że pytanie dotyczy tylko liczb, a tak czy inaczej jest to tylko sugestia . –

+0

Prosiłem o wyjaśnienia wcześniej. Zobacz komentarze do pierwszego pytania: mogą to być dowolne proste typy (w tym ciągi znaków). –

1

Oto rozwiązanie przy użyciu ExpandoObject przechowywać go po parsowania go samodzielnie. Teraz dodaje wszystkie wartości jako string s, ale możesz dodać trochę parsowania, aby spróbować przekształcić je w podwójne, int lub długie (prawdopodobnie zechcesz wypróbować je w tej kolejności).

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; 
} 

używać go jak:

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

Znowu problem wynika z faktu, że ciąg znaków może zawierać ','. Blindly splitting nie jest dobrym pomysłem w tym przypadku.Co jeśli wejście to: 'a = 1, b = 2, c = 'To, mój przyjacielu, jest ciągiem'' –

+0

Hm, dobry punkt; ale o to chodzi, czym dokładnie jest ten format? Czy '' 'jest prawidłowym separatorem ciągów? A co z ''? Jak uniknąć tych separatorów, jeśli chcesz, aby jeden w ciągu? W skrócie, nie wiem, że format jest bardzo dobrze zdefiniowany –

+0

Uzgodnione, nie wiemy zbyt wiele na temat danych wejściowych i jak został oczyszczony (i jeśli w ogóle ma nad nim kontrolę) –