zrabzdn
zrabzdn

Reputation: 995

Loop through object properties without reflection

I have class MyModel and some object of MyModel.

I need for-loop or foreach properties of object without reflection. How implemented?

Class example:

public class MyModel
{
    public string Level1_TypeName { get; set; }
    public string Level1_AttrType { get; set; }
    public string Level1_AttrValue { get; set; }
    public string Level2_TypeName { get; set; } 
    public string Level2_AttrType { get; set; }
    public string Level2_AttrValue { get; set; }
    public string Level3_TypeName { get; set; } 
    public string Level3_AttrType { get; set; }
    public string Level3_AttrValue { get; set; }
    public string Level4_TypeName { get; set; } 
    public string Level4_AttrType { get; set; }
    public string Level4_AttrValue { get; set; }
    public string Level5_TypeName { get; set; } 
    public string Level5_AttrType { get; set; }
    public string Level5_AttrValue { get; set; }
    public string Level6_TypeName { get; set; }  
}

Upvotes: 1

Views: 3607

Answers (4)

Ashwin Gatadi
Ashwin Gatadi

Reputation: 1

Below code does not use reflections

using System.ComponentModel;

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(instance);
foreach (PropertyDescriptor prop in props)
{   
}

Upvotes: 0

Sean
Sean

Reputation: 62472

If you're looking to avoid reflection then you're going to have to write code by hand. You could add an method that returns an enumerator:

IEnumerable<Tuple<int,string,string,string>> GetLevels()
{
  yield return Tuple.Create(1, Level1_TypeName, Level1_AttrType, Level1_AttrValue);
  yield return Tuple.Create(2, Level2_TypeName, Level2_AttrType, Level2_AttrValue);
  yield return Tuple.Create(3, Level3_TypeName, Level3_AttrType, Level3_AttrValue);
  yield return Tuple.Create(4, Level4_TypeName, Level4_AttrType, Level4_AttrValue);
  yield return Tuple.Create(5, Level5_TypeName, Level5_AttrType, Level5_AttrValue);
  yield return Tuple.Create(6, Level6_TypeName, Level6_AttrType, Level6_AttrValue);
}

Now you can say:

foreach(var i in myModel.GetLevels())
{
  Console.WriteLine("{0},{1},{2},{3}",i.Item1,i.Item2,i.Item3,i.Item4);
}

Upvotes: 1

SynerCoder
SynerCoder

Reputation: 12766

You can use reflection to make a dictionary with all your values:

var obj = new MyModel();
var dictionary = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToDictionary(p => p.Name, p => p.GetGetMethod().Invoke(obj, null));
foreach (var kv in dictionary)
    Console.WriteLine(kv.Key + ": " + kv.Value ?? "null");

But I do recommend you read and use the answer of Jon Skeet

If you don't want to use reflection you can't loop through an objects properties.

You can use a bit of reflection in your model to implement an ienumerable:

public class MyModel : IEnumerable<KeyValuePair<string, object>>
{
    public string Level1_TypeName { get; set; }
    public string Level1_AttrType { get; set; }
    public string Level1_AttrValue { get; set; }
    public string Level2_TypeName { get; set; }
    public string Level2_AttrType { get; set; }
    public string Level2_AttrValue { get; set; }
    public string Level3_TypeName { get; set; }
    public string Level3_AttrType { get; set; }
    public string Level3_AttrValue { get; set; }
    public string Level4_TypeName { get; set; }
    public string Level4_AttrType { get; set; }
    public string Level4_AttrValue { get; set; }
    public string Level5_TypeName { get; set; }
    public string Level5_AttrType { get; set; }
    public string Level5_AttrValue { get; set; }
    public string Level6_TypeName { get; set; }

    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        return this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToDictionary(p => p.Name, p => p.GetGetMethod().Invoke(this, null)).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

You can then use your class like this:

var obj = new MyModel();
foreach(var kv in obj)
    Console.WriteLine(kv.Key + ": " + kv.Value ?? "null");

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1499780

I would strongly suggest that you take two actions:

  • Create a new type to encapsulate the combination of TypeName, AttrType, AttrValue
  • Change your model to contain a collection of that class rather than several separate properties.

At that point, it will be really easy to iterate over the properties without using reflection... and your code will be much clearer, too.

Upvotes: 11

Related Questions