向匿名类添加额外属性

时间:2013-07-23 07:48:39

标签: c# asp.net-mvc

有没有办法为匿名类添加额外的属性(或创建具有额外属性的新实例)?

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

4 个答案:

答案 0 :(得分:6)

不,你不能这样做。但是你可以重新定义它:

dynamic viewData = new { @class = cssClasses };
if (suppliedId != null)
{
    viewData = new { @class = viewData.@class, yourExtra = Property };
}

请注意,我将其更改为dynamic。这样您就可以编辑属性而无需转换为dynamic

答案 1 :(得分: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;

代替。

答案 2 :(得分:1)

感谢Patryk发表评论,我使用了ExpandoObject,并让它像这样工作:

dynamic viewData = new ExpandoObject();
viewData.@class = 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中工作的关键,这样它就可以作为EditorFor等中的additionalViewData参数传递。

在我传递匿名类并需要自己添加的情况下,我正在使用反射(并利用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");
}

答案 3 :(得分:0)

您可以使用反射来达到要求,您可以通过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);