8

追加のプロパティを匿名クラスに追加する (または追加のプロパティを使用して新しいインスタンスを作成する) 方法はありますか?

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

4 に答える 4

3

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

その最後の行は、EditorFor などで additionalViewData パラメーターとして渡すことができるように、MVC で動作させるための鍵でした。

匿名クラスが渡され、自分で追加する必要がある状況では、リフレクションを使用しています (そして、IDictionary を実装する ExpandoObject を利用しています)。これが機能することを確認するために書いた単体テストです。

[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");
}
于 2013-07-24T01:47:36.300 に答える
3

匿名型に追加のプロパティを追加することはできませんが、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;

代わりは。

于 2013-07-23T08:25:04.173 に答える
0

Reflectionを使用することで要件を達成でき、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);
于 2016-06-01T12:36:13.260 に答える