2013-07-23 17 views
6

Czy istnieje sposób na dodanie dodatkowych właściwości do anonimowej klasy (lub utworzenie nowej instancji z dodatkowymi właściwościami)?Dodawanie dodatkowych właściwości do anonimowej klasy

string cssClasses = "hide"; 
object viewData = new { @class = cssClasses }; 
if (suppliedId != null) 
{ 
    // add an extra id property to the viewData somehow... 
    // desired end result is { @id = suppliedId, @class = cssClasses } 
} 
// ... code will be passing the viewData as the additionalViewData parameter in asp.mvc's .EditorFor method 

Odpowiedz

1

Dzięki komentarzu Patryk Dałem mu szansę przy użyciu ExpandoObject, ale to działa tak:

dynamic viewData = new ExpandoObject(); 
[email protected] = cssClasses; 
if (controlId != null) 
    viewData.id = controlId; 
if (title != null) 
    viewData.title = title; 
// put the result into a route value dictionary so that MVC's EditorFor (etc) can interpret it 
var additionalViewData = new RouteValueDictionary(viewData); 

Ta ostatnia linia była kluczem do coraz to pracę w MVC tak, że może być przekazywana jako parametr additionalViewData w edytorzeDla itp.

W sytuacjach, w których otrzymuję anonimową klasę i muszę sam ją dodać, używam odbicia (i korzystam z implementacji IDael). Oto test jednostka pisałem aby sprawdzić, czy to działa:

[TestMethod] 
public void ShouldBeAbleToConvertAnAnonymousObjectToAnExpandoObject() 
{ 
    var additionalViewData = new {id = "myControlId", css = "hide well"}; 
    dynamic result = new ExpandoObject(); 
    var dict = (IDictionary<string, object>)result; 
    foreach (PropertyInfo propertyInfo in additionalViewData.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) 
    { 
    dict[propertyInfo.Name] = propertyInfo.GetValue(additionalViewData, null); 
    } 
    Assert.AreEqual(result.id, "myControlId"); 
    Assert.AreEqual(result.css, "hide well"); 
} 
6

Nie, nie możesz tego zrobić. Można go przedefiniować, choć:

dynamic viewData = new { @class = cssClasses }; 
if (suppliedId != null) 
{ 
    viewData = new { @class = [email protected], yourExtra = Property }; 
} 

pamiętać, że zmienił go do dynamic. To jest tak, że możesz edytować właściwości bez przesyłania do dynamic.

+3

Tak, albo to, albo skorzystać z '' dynamic' ExpandoObject' zamiast :) –

+0

@ PatrykĆwiek Tak, to prawda. Bardzo lubię ExpandoObject tbh, jest całkiem fajnie. –

+0

Nie rozumiem, dlaczego nie trzymałeś 'obiektu' w kodzie? Oba typy anonimowe to "obiekt". –

2

Nie można dodawać dodatkowych właściwości do anonimowych typów, ale można używaćdwóch typów anonimowych.

Jeśli nie podoba dynamic (a istnieją powody, aby nie), można zrobić:

object viewData; 
if (suppliedId == null) 
    viewData = new { @class = cssClasses, }; 
else 
    viewData = new { @id = suppliedId, @class = cssClasses, }; 

Jeśli chcesz zachować oddzielne odniesienia dokładnie wpisane do każdego obiektu instancji, a następnie użyć:

var viewDataSimple = new { @class = cssClasses, }; 
var viewDataExtra = new { @id = suppliedId, @class = cssClasses, }; 
object viewDataToUse; 
if (suppliedId == null) 
    viewDataToUse = viewDataSimple; 
else 
    viewDataToUse = viewDataExtra; 

zamiast tego.

+0

+1 Tak, właśnie to robiłem. Teraz mam kilka dodatkowych właściwości, więc liczba permutacji wymyka się spod kontroli. –

+0

@ JonathanMoffatt Więc może naprawdę chcesz [klasy "ExpandoObject'] (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) w" System.Dynamiczna przestrzeń nazw. Działa dokładnie poprzez dodawanie nowych członków. Zobacz przykłady na linku podałem tam. Edycja: Ah, właśnie widziałem z twojej nowej odpowiedzi, którą już odkryłeś. –

0

można osiągnąć stosując wymóg Reflection, można dodać nową właściwość przez keyvalue Pair.

string cssClasses = "hide"; 
     object viewData = new { @class = cssClasses }; 
     dynamic expandoData = new ExpandoObject(); 
     var processedData = expandoData as IDictionary<String, object>; 
     if (viewData != null) 
     { 
      PropertyInfo[] properties = viewData.GetType().GetProperties(); 
      foreach (var prop in properties) 
      { 
       if (prop == null) continue; 
       object valueObj = viewData .GetType().GetProperty(prop.Name).GetValue(viewData , null); 
       processedData[prop.Name.ToString()] = valueObj; 
      } 
     }   
     processedData["AdditionalPropertyName"] = AdditionalProperty; 
     var infoJson = JsonConvert.SerializeObject(processedData); 
+0

powinieneś opisać rozwiązanie, które już podałeś, jest to tylko różnica - nie jest to właściwa odpowiedź – DomTomCat

Powiązane problemy