Jak stworzyć własny typ dynamiczny lub obiekt dynamiczny w C #?


142

Jest na przykład właściwość klasy ViewBagControllerBase i możemy dynamicznie pobierać / ustawiać wartości i dodawać dowolną liczbę dodatkowych pól lub właściwości do tego obiektu, co jest fajne. Chcę użyć czegoś takiego, poza aplikacją MVC i Controllerklasą w innych rodzaje aplikacji. Kiedy próbowałem stworzyć obiekt dynamiczny i ustawić jego właściwość jak poniżej:

1. dynamic MyDynamic = new { A="a" };
2. MyDynamic.A = "asd";
3. Console.WriteLine(MyDynamic.A);

Otrzymałem RuntimeBinderExceptionz wiadomością Właściwość lub indeksator '<> f__AnonymousType0.A' nie może być przypisany - jest odczytywany tylko w linii 2. Również sugeruję, że nie jest to do końca to, czego szukam. Może jest jakaś klasa, która pozwoli mi zrobić coś takiego:

??? MyDynamic = new ???();
MyDynamic.A = "A";
MyDynamic.B = "B";
MyDynamic.C = DateTime.Now;
MyDynamic.TheAnswerToLifeTheUniverseAndEverything = 42;

z dynamicznymi właściwościami dodawania i ustawiania.

Odpowiedzi:


293
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.A = "A";
MyDynamic.B = "B";
MyDynamic.C = "C";
MyDynamic.Number = 12;
MyDynamic.MyMethod = new Func<int>(() => 
{ 
    return 55; 
});
Console.WriteLine(MyDynamic.MyMethod());

Przeczytaj więcej o klasie ExpandoObject i więcej przykładów: Reprezentuje obiekt, którego elementy członkowskie mogą być dynamicznie dodawane i usuwane w czasie wykonywania.


3
Zagłosuj na tę funkcję w programie Visual Studio UserVoice .
orad

35

Niedawno musiałem pójść o krok dalej, a mianowicie uczynić dodatki właściwości w obiekcie dynamicznym, same dynamiczne, w oparciu o wpisy zdefiniowane przez użytkownika. Przykłady tutaj oraz z dokumentacji ExpandoObject firmy Microsoft nie dotyczą w szczególności dynamicznego dodawania właściwości, ale można je wywnioskować na podstawie sposobu wyliczania i usuwania właściwości. W każdym razie pomyślałem, że to może być dla kogoś pomocne. Oto niezwykle uproszczona wersja sposobu dodawania prawdziwie dynamicznych właściwości do ExpandoObject (ignorując słowo kluczowe i inne sposoby obsługi):

        // my pretend dataset
        List<string> fields = new List<string>();
        // my 'columns'
        fields.Add("this_thing");
        fields.Add("that_thing");
        fields.Add("the_other");

        dynamic exo = new System.Dynamic.ExpandoObject();

        foreach (string field in fields)
        {
            ((IDictionary<String, Object>)exo).Add(field, field + "_data");
        }

        // output - from Json.Net NuGet package
        textBox1.Text = Newtonsoft.Json.JsonConvert.SerializeObject(exo);

Czy ktoś wie, dlaczego musimy wpisać rzut, aby uzyskać dostęp do Addmetody? Wydaje mi się to dziwne.
Vimes

Dzieje się tak, ponieważ ExpandoObject nie ujawnia bezpośredniej metody Add. Jeśli spróbujesz użyć .Add, potraktuje to wyrażenie tak, jakbyś chciał dodać element członkowski „Add” do obiektu. Musisz ujawnić podstawową strukturę danych, w zasadzie przechodząc do interfejsu Dictionary, aby uzyskać dostęp do metody Add. Dotyczy to również usuwania członka lub czegokolwiek innego, co jest oferowane w słowniku, ale nie jest ujawniane w samym ExpandoObject. Nowsza dokumentacja wydaje się lepiej wyjaśniać to wymaganie: docs.microsoft.com/en-us/dotnet/api/ ...
AlienFromCA

Dzięki, Alien. Czy przychodzi Ci do głowy jakiś powód, dla którego API zostało zaprojektowane w ten sposób, poza przypadkową decyzją? O ile wiem, to kiepski projekt API.
Vimes

32

ExpandoObject jest tym, czego szukasz.

dynamic MyDynamic = new ExpandoObject(); // note, the type MUST be dynamic to use dynamic invoking.
MyDynamic.A = "A";
MyDynamic.B = "B";
MyDynamic.C = "C";
MyDynamic.TheAnswerToLifeTheUniverseAndEverything = 42;

11

Możesz użyć tego, ExpandoObject Classco jest w System.Dynamicprzestrzeni nazw.

dynamic MyDynamic = new ExpandoObject();
MyDynamic.A = "A";
MyDynamic.B = "B";
MyDynamic.C = "C";
MyDynamic.SomeProperty = SomeValue
MyDynamic.number = 10;
MyDynamic.Increment = (Action)(() => { MyDynamic.number++; });

Więcej informacji można znaleźć w ExpandoObject MSDN


9
dynamic myDynamic = new { PropertyOne = true, PropertyTwo = false};


7
 var data = new { studentId = 1, StudentName = "abc" };  

Lub wartość jest obecna

  var data = new { studentId, StudentName };
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.