4

I have several get properties that I would like to be able to loop through like an array of functions. 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?

2
  • 3
    The documentation for Func<TResult> shows you no less than four ways of creating them correctly. Also, considering just how much is broken in your code, you should spend more time reading the C# tutorial. Commented Mar 9, 2013 at 23:23
  • Without using Reflection, you would have to create a data structure (e.g. List) to hold references to each property; then iterate over that data structure. Commented Mar 9, 2013 at 23:25

6 Answers 6

7

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

5 Comments

That will only hold the values of each property, and it will not reflect updates to the properties (or rather the backing fields) without reloading the List.
What are the prop1, ..., prop6 supposed to be?
@poke I'm not entirely sure if you want to reference the properties themselves or just their values. I've updated my answer to explain how to get both, in two different ways.
@KennethK. I wasn't sure if the OP was looking to create a list of the actual properties or a list of their values.
Just pointing it out so it would be clear to everyone reading the post. (Of course, it doesn't apply now since your edit!) :)
0

You can try to use GetProperties

GetProperties Documentation

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)

Comments

0

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. (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.

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

}

Comments

0

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 {

    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 {

    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

`

Comments

0

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:

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

Or direct access :

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.