user2125899
user2125899

Reputation: 117

C# array of properties

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?

Upvotes: 4

Views: 25908

Answers (6)

MohsenB
MohsenB

Reputation: 1921

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

Upvotes: 0

Tom
Tom

Reputation: 888

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

`

Upvotes: 0

p.s.w.g
p.s.w.g

Reputation: 148980

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

Upvotes: 1

Guffa
Guffa

Reputation: 700152

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

}

Upvotes: 0

poke
poke

Reputation: 387507

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.

Upvotes: 7

Mario Corchero
Mario Corchero

Reputation: 5565

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)

Upvotes: 0

Related Questions