有没有办法在C#中向对象添加键/值语法?

有没有办法在C#中向对象添加键/值语法?,c#,extension-methods,C#,Extension Methods,我有一个叫做CottonCandy的物体。CottonCandy有几个特性: 弥撒 卷 总糖 颜色 如果我可以向CottonCandy添加一些内容,以便检索如下属性,那就太好了: var colors = cottonCandy["Colors"]; 通过阅读,您似乎可以通过以下方式获得值: cottonCandy.GetType().GetProperty("Colors").GetValue(cottonCandy, null); 您可以轻松地将其包装到一个方法中: var colo

我有一个叫做CottonCandy的物体。CottonCandy有几个特性:

  • 弥撒
  • 总糖
  • 颜色
如果我可以向CottonCandy添加一些内容,以便检索如下属性,那就太好了:

var colors = cottonCandy["Colors"];
通过阅读,您似乎可以通过以下方式获得值:

cottonCandy.GetType().GetProperty("Colors").GetValue(cottonCandy, null);
您可以轻松地将其包装到一个方法中:

var colors = cottonCandy.GetPropertyValue("Colors");

但是我更喜欢键/值语法
cottonCandy[“Colors”]
。有什么方法可以做到这一点吗?

如果您的类是一个简单的数据对象,没有任何行为,只有这样简单的属性,那么您可以将其设置为一个
字典

var map = new Dictionary<string, whatever> { { "Colors", ... }, { "Mass", ... } ... };
map["Colors"] = ...;
var-map=newdictionary{{“Colors”,…},{“Mass”,…};
地图[“颜色”]=。。。;

否则,您应该使用您已经提到的反射。

这不是键/vaue语法。但是,如果您决定使用扩展,则可以使用此扩展方法。这个包中有类似的扩展

publicstatict GetFieldValue(此对象对象对象,字符串字段名)
{
T结果;
PropertyInfo PropertyInfo=obj.GetType().GetProperty(字段名);
if(propertyInfo!=null)
{
结果=(T)propertyInfo.GetValue(obj);
}
其他的
{
抛出新的FieldAccessException($“{fieldName}找不到”);
}
返回结果;
}
您可以通过访问访问更多分机。可能会提供有关方法使用和结果的线索

更新:

您可以像这样组合扩展方法和索引器:

public class TestClass
{
    public string this[string field]
    {
        get => this.GetFieldValue<string>(field);
        set => this.TrySetFieldValue(field, value);
    }
}
公共类TestClass
{
公共字符串此[字符串字段]
{
get=>this.GetFieldValue(字段);
set=>this.TrySetFieldValue(字段,值);
}
}

实际上有一种方法。你可以用。但您需要具有相同的字段类型,或者在
对象中框选值

class CottonCandy
{
    private int Mass { get; set; }
    private int Volume { get; set; }
    private int TotalSugar { get; set; }
    private int Colors { get; set; }

    public int this[string field]
    {
        get
        {
            PropertyInfo propertyInfo = typeof(CottonCandy).GetProperty(field);
            if(propertyInfo == null)
                throw new ArgumentException("Invalid field");
            return (int)propertyInfo.GetValue(this);
        }
    }
}

请尝试查看对象索引器:

实现这一点的一种方法是使用索引器,并使用“nameof”操作符将索引器字符串值与可用属性进行比较。这将使代码更加冗长,但避免了反射的需要

但是,请确保这确实是您真正想要的,因为如果您以这种方式访问属性,您将不再获得编译时检查的好处。

您可以这样做

public class CottonCandy
    {

        public string Mass { get; set; }
        public string Volume { get; set; }
        public string TotalSugar { get; set; }
        public string Colors { get; set; }
        public string this[string key]
        {
            get
            {
                switch (key)
                {
                    case "Mass":
                        return this.Mass;
                    case "Volume":
                        return this.Volume;
                    case "TotalSugar":
                        return this.TotalSugar;
                    case "Colors":
                        return this.Colors;
                    default:
                        return "";
                }

            }
            set
            {
                switch (key)
                {
                    case "Mass":
                        this.Mass = value; break;
                    case "Volume":
                        this.Volume = value; break;
                    case "TotalSugar":
                        this.TotalSugar = value; break;
                    case "Colors":
                        this.Colors = value; break;
                    default:
                        break;
                }
            }
        }


    }

您的用例是否希望有一些类,但有一组未知的属性,您可能希望“附加”到它,而这些属性只有在运行时才知道?如果是这样的话,您可能正在寻找,但要从C#使用它,您还必须使用
dynamic
。(但是,如果你要走这条路,问问自己,像C#这样的静态类型语言是否是适合这项工作的工具)你可以将反射方法与。在这里,您的方法的一般问题是,如果每个属性可能是不同类型的,您将如何进行这项工作。您能解释一下为什么要这样做,而不是简单地按照“代码>棉花糖”来访问属性。颜色< /代码>?我认为它极大地提高了代码的质量,如果它成为所有其他开发人员都会立即识别的标准,但无论哪种方式,听起来都像是XY问题。事实上,你认为你必须实现这一点,这听起来更像是我的问题。你可以用它来完成。不幸的是,这是一门繁忙的课程。很遗憾,没有一种方法可以继承字典语法。宾果!这正是我想要的。谢谢。但我不推荐这种方法,因为至少会丢失IntelliSense自动完成和编译时检查
public class CottonCandy
    {

        public string Mass { get; set; }
        public string Volume { get; set; }
        public string TotalSugar { get; set; }
        public string Colors { get; set; }
        public string this[string key]
        {
            get
            {
                switch (key)
                {
                    case "Mass":
                        return this.Mass;
                    case "Volume":
                        return this.Volume;
                    case "TotalSugar":
                        return this.TotalSugar;
                    case "Colors":
                        return this.Colors;
                    default:
                        return "";
                }

            }
            set
            {
                switch (key)
                {
                    case "Mass":
                        this.Mass = value; break;
                    case "Volume":
                        this.Volume = value; break;
                    case "TotalSugar":
                        this.TotalSugar = value; break;
                    case "Colors":
                        this.Colors = value; break;
                    default:
                        break;
                }
            }
        }


    }