2013-07-23 5 views
6

Есть ли способ добавить дополнительные свойства к анонимному классу (или создать новый экземпляр с дополнительными свойствами)?Добавление дополнительных свойств анонимному классу

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 

ответ

1

Благодаря комментарий от Patryk я дал ему идти, используя ExpandoObject и получило это работает так:

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

Это последняя строка была ключ к получению его работой в MVC, так что он может быть принят как параметр дополнительногоViewData в EditorFor и т. д.

В ситуациях, когда мне передают анонимный класс и нужно добавить его сам, я использую отражение (и используя ExpandoObject, реализующий IDictionary). Вот тестовый модуль я написал, чтобы проверить, что это работает:

[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

Нет, вы не можете этого сделать. Вы можете переопределить его, хотя:

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

Обратите внимание, что я изменил его dynamic. Это просто, чтобы вы могли редактировать свойства без литья до dynamic.

+3

Да, или это, или использовать '' dynamic' с ExpandoObject' вместо :) –

+0

@ PatrykĆwiek Да, верно. Мне очень нравится ExpandoObject tbh, это довольно круто. –

+0

Я не понимаю, почему вы не сохранили «объект» в коде? Оба анонимных типа, о которых идет речь, являются «объектами». –

2

Невозможно добавить дополнительные объекты к анонимным типам, но вы можете использовать два анонимных типа.

Если вам не нравится dynamic (и есть причины не), вы можете сделать:

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

Если вы хотите сохранить отдельные точно типизированных ссылки на каждый экземпляр объекта, а затем использовать:

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

вместо этого.

+0

+1 Да, это именно то, что я делал. Теперь у меня есть еще несколько дополнительных свойств, поэтому количество перестановок выходит из-под контроля. –

+0

@JonathanMoffatt Тогда, возможно, вы действительно хотите [класс ExpandoObject] (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) в 'System.Динамическое пространство имен. Он работает точно, добавляя новых членов, когда вы идете. См. Примеры по ссылке, которую я там привел. Изменить: Ах, только что увидел из вашего нового ответа, который вы уже узнали. –

0

Вы можете достичь требований с помощью Отражения, Вы можете добавить новое свойство с помощью KeyValue пары.

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

вы должны описать решение, которое вы предоставили на данный момент, это только diff - не правильный ответ – DomTomCat

Смежные вопросы