【问题标题】:C# properties as array notationC# 属性作为数组表示法
【发布时间】:2011-01-28 17:31:02
【问题描述】:

使用 JavaScript,可以使用点表示法或数组表示法访问对象。

var myArray = {e1:"elem1",e2:"elem2",e3:"elem3",e4:"elem4"};
var val1 = myArray["e1"];
var val2 = myArray.e1;

是否有可能使用 C# 来完成?

这是我尝试过的:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection frmVals)
{
  string value;
  Owner owner = new Owner();

  foreach (var key in frmVals.AllKeys)
  {
    value = frmVals[key];
    owner[key] = value;  
  }
}

【问题讨论】:

  • 为什么要使用这种表示法?
  • 不要这样做。也许还有其他合法的场景,但这(一个 ASP.NET MVC 控制器操作)绝对不是其中之一。你真的真的很想验证来自网络用户的输入。不要只是将任意值填充到任意命名的属性中。这只是要求安全问题。
  • 感谢您提供的有用信息。由于我是新手,我的想法是将输入值填充到强类型对象中,如果无法转换值,则会抛出异常。填充值后,如果没有例外,那么我将验证属性值的格式是否正确。在所有这些都得到验证之后,我可以将此对象传递给一个控件,并将其保存到数据库中。
  • 是的,您可以在 C# 4.0 中使用 ExpandoObject 执行此操作,但您不会在成员上获得智能感知。它基本上是一个实现 IDictionary 的动态对象。 msdn.microsoft.com/en-us/library/…

标签: c# arrays properties


【解决方案1】:

虽然没有办法完全使用 C# 来做到这一点。您可以通过多种方式更改代码以实现您的目标。首先,您可以使用这样的字典:

var something = new Dictionary<string, object>() {
    { "property", "value"},
    { "property1", 1}
};
foreach (var keyVal in something) {
    var property = keyVal.Key;
    var propertyValue = keyVal.Value;
}

另一种选择是动态执行:

dynamic somethingDyn = new System.Dynamic.ExpandoObject();
somethingDyn.property = "value";
somethingDyn.property1 = 1;

var somethingDynDict = (IDictionary<string, object>)somethingDyn;
var propValue = somethingDyn["property"];

foreach (var keyVal in somethingDynDict) {
    var property = keyVal.Key;
    var propertyValue = keyVal.Value;
}

如果您需要遍历强类型对象的属性,您可以使用反射:

var owner = new Metis.Domain.User();
var properties = owner.GetType().GetProperties();
foreach (var prop in properties) {
    object value = prop.GetValue(owner, null);
}

【讨论】:

  • Dictionary 方法不模仿该功能,因为它不提供属性样式的访问。
  • 我同意,但我认为让他了解可用选项非常重要,这样他才能评估完成任务的最佳方式。字典方法可能比使用强类型对象更好。
  • 我同意,我只是认为你注意到它与所描述的 JavaScript 功能不是一对一的匹配。
【解决方案2】:

我不建议这样做,但你可以在你的类中放置一个索引器,接受一个字符串,然后使用反射来读取该属性。比如:

public object this[string key]
{
  get
  {
    var prop = typeof(ThisClassName).GetProperty(key);
    if (prop != null)
    {
      return prop.GetValue(this, null);
    }
    return null;
  }
  set
  {
    var prop = typeof(ThisClassName).GetProperty(key);
    if (prop != null)
    {
      prop.SetValue(this, value, null);
    }
  }
}

【讨论】:

    【解决方案3】:

    Javascript 数组表示法不能在 C# 中使用。

    您需要使用点符号来访问对象的成员。

    您需要直接访问每个值并分配它:

    owner.key = frmVals[key];
    owner.key2 = frmVals[key2];
    

    有一些变通方法 - 使用字典、动态对象甚至反射,但 C# 不直接支持该场景。

    【讨论】:

      【解决方案4】:

      在 C# 中没有可能的语法等价物,但有一些方法可以近似相同的特征。

      您可以使用Dictionary 来模仿索引器类型的访问,但随后您将失去属性样式的访问。对于属性式访问,您可以在 C# 中使用匿名类型执行类似的操作,如下所示:

      var myType = new { e1="elem1",e2="elem2",e3="elem3",e4="elem4"};
      var val1 = myType.e1;
      

      但是,这不会创建数组或允许数组类型访问,也不允许在创建后修改类型。

      为了更接近 JavaScript 功能,您可以使用ExpandoObject 更接近地模仿这一点,或者您可以自己实现一些东西。

      为此,您需要一个具有构造函数的类,该构造函数可以从传入的数组中自动生成属性并公开一个索引器,该索引器又使用反射来查找命名属性。

      这种类型的初始化类似于:

      var myType = new MyType(new[]{
          {"e1", "elem1"},
          {"e2", "elem2"},
          {"e3", "elem3"},
          {"e4", "elem4"}});
      

      这假定每个元素定义都有一个子类型(可能使用TupleKeyValuePair。然后构造函数将采用该类型的IEnumerable&lt;T&gt;

      【讨论】:

      • 评论被删除,因为你忍了你的答案。
      • @Ben:感谢您的反馈。
      【解决方案5】:

      是的,这是可能的。

      有两种可能:

      1) 键和值列表是动态的。

      • 数组表示法由例如提供。 System.Collections.Generic.Dictionary&lt;string, blah&gt;
      • 可以通过 DLR 魔术和 dynamic 关键字提供成员访问表示法。

      2) 键和值的列表是静态的。

      • C# 编译器已提供成员访问表示法。
      • 可以使用反射来获得数组表示法(希望通过缓存来提高性能)。

      在静态情况下,成员访问表示法要快得多。在动态情况下,数组表示法会快一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-26
        • 2015-11-12
        • 2011-01-05
        • 2014-04-01
        • 1970-01-01
        • 2011-04-25
        • 2022-01-08
        • 1970-01-01
        相关资源
        最近更新 更多