简体   繁体   English

C#属性数组

[英]C# array of properties

I have several get properties that I would like to be able to loop through like an array of functions. 我有几个get属性,它们希望像函数数组一样循环遍历。 I would like to be able to do something like this 我希望能够做这样的事情

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

This code is very broken, but I think it conveys the idea of what I would like to be able to do. 这段代码很破损,但是我认为它传达了我想要做的想法。 Anyone know how I can achieve this? 有人知道我能做到这一点吗?

You could use reflection to access the properties within your type: 您可以使用反射来访问类型内的属性:

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

Note that reflection is slow and you shouldn't use this if there is a better way. 请注意,反射速度很慢,如果有更好的方法,则不应使用此功能。 For example when you know that there are only 6 properties, just go through them individually. 例如,当您知道只有6个属性时,只需对它们进行逐一检查即可。

You can try to use GetProperties 您可以尝试使用GetProperties

GetProperties Documentation GetProperties文档

Example: 例:

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

Further Info: 更多信息:
The example for GetProperties with flags is really nice, and it can be useful for you if you want to access to a specific subset of Properties (Like only the Public Ones) 带有标志的GetProperties的示例非常好,如果您要访问属性的特定子集(仅像公共对象),则对您很有用。

If you know all the properties you want to loop through already, then you can try this 如果您已经知道要遍历的所有属性,则可以尝试此操作

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

If not, you can use something like this: 如果没有,您可以使用以下方法:

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

The code is not so far from working. 该代码离工作不远了。 The myProperties variable should be an array, and you need to create functions that read from the properties. myProperties变量应该是一个数组,并且您需要创建从属性读取的函数。 (The property getter is actually implemented as a function, but you can't call it as a function or get a reference to it.) Then you use them by calling them. (属性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;
  }

}

If you're needing your Properties in an Array, because you're needing to (as I did) Set and/or Get several related (and same-Typed) Properties, here's what you can do. 如果您需要数组中的属性,因为您需要(和我一样)设置和/或获取几个相关的(和相同类型的)属性,这就是您可以做的。 I know Reflection is "'slow'", but for my use cases, the duplicate code (and therefore error chance) reduction benefits far outweigh any "'slowness'" (which are insignificant) due to Reflection. 我知道反射是“'慢'的”,但是对于我的用例来说,减少重复代码(因此减少错误机会)的好处远远超过了任何由于反射而导致的““慢””(无关紧要)。 This does not handle Indexed Properties, but a version to so can easily be created from this. 这不处理索引属性,但是可以从中轻松创建一个这样的版本。

` public class MyClass { `公共类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

` `

` public class ReflectionHelper { `公共类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

` `

You can use an array buffer and get all prop from it. 您可以使用数组缓冲区并从中获取所有支持。 in this way you can get and set very fast: 通过这种方式,您可以非常快速地获取和设置:

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]; }

Now can access all prop with buf : 现在可以使用buf访问所有道具:

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

Or direct access : 或直接访问:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM