c#属性数组

本文关键字:数组 属性 | 更新日期: 2023-09-27 18:03:04

我有几个get属性,我希望能够像函数数组一样循环。我希望能够做这样的事情

public int prop1 { get; }
public string prop2 { get; }
public int[] prop3 { get; }
public int prop4 { get; }
public string prop5 { get; }
public string prop6 { get; }
Func<var> myProperties = { prop1, prop2, prop3, prop4, prop5, prop6 };
ArrayList myList = new ArrayList();
foreach( var p in myProperties)
{
    myList.Add(p);
}

这段代码非常糟糕,但我认为它传达了我想要能够做的事情的想法。有人知道我该怎么做吗?

c#属性数组

您可以使用反射来访问类型中的属性:

class MyType
{
    public int prop1 { get; }
    public string prop2 { get; }
    public int[] prop3 { get; }
    public int prop4 { get; }
    public string prop5 { get; }
    public string prop6 { get; }
    public List<string> GetAllPropertyValues()
    {
        List<string> values = new List<string>();
        foreach (var pi in typeof(MyType).GetProperties())
        {
            values.Add(pi.GetValue(this, null).ToString());
        }
        return values;
    }
}

请注意,反射很慢,如果有更好的方法,你不应该使用它。例如,当您知道只有6个属性时,只需逐个查看它们。

如果您已经知道要循环遍历的所有属性,那么您可以尝试使用

List<Reflection.PropertyInfo> myProperties = new List()<object>
{
    typeof(SomeType).GetProperty("prop1"), 
    typeof(SomeType).GetProperty("prop2"), 
    typeof(SomeType).GetProperty("prop3"), 
    typeof(SomeType).GetProperty("prop4"), 
    typeof(SomeType).GetProperty("prop5"), 
    typeof(SomeType).GetProperty("prop6")
};
foreach(var p in myProperties)
{
    var value = p.GetValue(someObject, new object[0]);
    myList.Add(p);
}

如果没有,你可以这样写:

var myProperties = 
    from pi in someObject.GetType().GetProperties()
    select new 
    {
        pi.Name, 
        Value = pi.GetValue(object, new object[0])
    };
foreach(var p in myProperties)
{
    myList.Add(p.Value);
}

您可以尝试使用GetProperties

getproperty文档

的例子:

PropertyInfo[] myPropertyInfo;
// Get the properties of 'Type' class object.
myPropertyInfo = Type.GetType("System.Type").GetProperties();
Console.WriteLine("Properties of System.Type are:");
for (int i = 0; i < myPropertyInfo.Length; i++)
{
    Console.WriteLine(myPropertyInfo[i].ToString());
}
进一步信息:


带有标志的GetProperties示例非常好,如果您想访问属性的特定子集(例如Public Properties)

,它可能对您很有用。

代码离工作还很远。myProperties变量应该是一个数组,您需要创建从属性中读取的函数。(属性getter实际上是作为函数实现的,但你不能作为函数调用它或获取对它的引用。)然后通过调用它们来使用它们。

public class MyClass {
  public int prop1 { get; set; }
  public string prop2 { get; set; }
  public int[] prop3 { get; set; }
  public int prop4 { get; set; }
  public string prop5 { get; set; }
  public string prop6 { get; set; }
  public ArrayList GetProperties() {
    Func<object>[] myProperties = {
      () => prop1, () => prop2, () => prop3,
      () => prop4, () => prop5, () => prop6
    };
    ArrayList myList = new ArrayList();
    foreach (var p in myProperties) {
      myList.Add(p());
    }
    return myList;
  }
}

如果你需要你的数组属性,因为你需要(像我一样)设置和/或获取几个相关的(和相同类型的)属性,这里是你可以做的。我知道反射是"慢"的,但是对于我的用例来说,减少重复代码(以及因此产生的错误机会)的好处远远超过反射带来的任何"慢"(这是微不足道的)。这并不处理索引属性,但可以很容易地从它创建一个版本。

'公共类MyClass{

    private string[] myBoolPropertyNames = 
    {
        nameof(MyBool1Property),
        nameof(MyBool2Property)
    }; // MyBoolPropertyNames =
    private MyClass()
    {
        foreach (var propertyName in myBoolPropertyNames)
        {
            ReflectionHelper.SetPropertyValue
            (
                parentObject: this,
                propertyName: propertyName,
                untypedPropertyValue: true
            ); // SetPropertyValue
        } // foreach (var propertyName in myBoolPropertyNames)
        foreach (var propertyName in myBoolPropertyNames)
        {
            bool boolPropertyValue = ReflectionHelper.GetPropertyValue<bool>
            (
                parentObject: this,
                propertyName: propertyName
            ); // SetPropertyValue
            Console.WriteLine($"Property '{propertyName}' value: {boolPropertyValue}");
        } // foreach (var propertyName in myBoolPropertyNames)
    }
    public bool MyBool1Property { get; set; }
    public bool MyBool2Property { get; set; }
} // MyClass

'公共类ReflectionHelper{

    public static PropertyType GetPropertyValue<PropertyType>
    (
        object parentObject,
        string propertyName
    )
    {
        if (parentObject == null)
        {
            throw new ArgumentException
            (
                $"Missing '{nameof(parentObject)}'."
            );
        } // if (parentObject == null)
        PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
        if (propertyInfo == null)
        {
            throw new ArgumentException
            (
                "No PropertyInfo found for Property: " + propertyName
            );
        } // if (propertyInfo == null)
        object untypedPropertyValue = propertyInfo.GetValue(obj: parentObject);
        Type propertyType = 
        (
            Nullable.GetUnderlyingType(propertyInfo.PropertyType) 
            ?? propertyInfo.PropertyType
        ); // propertyType = 
        object typedPropertyValue = 
        (
            (untypedPropertyValue == null) 
            ? null 
            : Convert.ChangeType(untypedPropertyValue, propertyType)
        ); // typedPropertyValue = 
        return (PropertyType)typedPropertyValue;
    } // GetPropertyValue
    public static void SetPropertyValue
    (
        object parentObject,
        string propertyName,
        object untypedPropertyValue
    )
    {
        if (parentObject == null)
        {
            throw new ArgumentException
            (
                $"Missing '{nameof(parentObject)}'."
            );
        } // if (parentObject == null)
        PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
        if (propertyInfo == null)
        {
            throw new ArgumentException
            (
                "No PropertyInfo found for Property: " + propertyName
            );
        } // if (propertyInfo == null)
        Type propertyType = 
        (
            Nullable.GetUnderlyingType(propertyInfo.PropertyType) 
            ?? propertyInfo.PropertyType
        ); // propertyType = 
        object typedPropertyValue =
        (
            (untypedPropertyValue == null)
            ? null
            : Convert.ChangeType(untypedPropertyValue, propertyType)
        ); // typedPropertyValue = 
        propertyInfo.SetValue
        (
            obj: parentObject, 
            value: typedPropertyValue
        ); // propertyInfo.SetValue
    } // SetPropertyValue
} // ReflectionHelper

"

您可以使用数组缓冲区并从中获取所有道具。通过这种方式,您可以非常快速地获取和设置:

public object[] buf = new object[5];
public int prop1 { get => buf[0]; }
public string prop2 { get => buf[1]; }
public int[] prop3 { get => buf[2]; }
public int prop4 { get => buf[3]; }
public string prop5 { get => buf[4]; }
public string prop6 { get => buf[5]; }

现在可以访问所有道具与buf:

foreach (var item in buf) {
  myList.Add(item);
}

或直接访问:

buf[1] = 10;
x = buf[1];