Mohamed Hasan
Mohamed Hasan

Reputation: 237

Reflection: Get All properties that implements an interface in a parameter Object

I have a class which has many objects of other classes:

public class Rootobject
{
    public USD USD { get; set; }
    public CAD CAD { get; set; }
    public EUR EUR { get; set; }
    public AED AED { get; set; }
    public AFN AFN { get; set; }
    public ALL ALL { get; set; }
}

Each of these classes implements an interface called ICurrency; the ICurrency Interface has a string property called "symbol" like that:

public class EUR : ICurrency 
{/*code logic*/}

Finally I have a method Which takes the RootObject instance as a parameter;

public object Add22(Rootobject rootobject)
{}

I need to get all the values of the "symbol" property of all the instances passed in the rootobject variable.

I think this can easily be done through reflection by creating a list of ICurrency and adding all the objects in it then looping through it.

Am I right? and if yes; then how to make it? or there is a better approach?

Upvotes: 2

Views: 3141

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131722

You can use Type.GetProperties to get a type's properties and Type.IsAssignableFrom to find whether a property can be assigned to an ICurrency variable. You can retrieve all matching properties with a LINQ query :

var currencyProps=typeof(Rootobject).GetProperties()                                   
                   .Where(pi=>typeof(ICurrency).IsAssignableFrom(pi.PropertyType))
                   .ToArray();

or

var currencyProps=( from pi in typeof(Rootobject).GetProperties()                                   
                    where typeof(ICurrency).IsAssignableFrom(pi.PropertyType)
                  ).ToArray();

You can cache the currencyProps array in a static field and reuse it with any object :

static PropertyInfo[] _currencyProps;

static void InitializeCurrencyProps()
{
    var currencyProps=( from pi in typeof(RootObject).GetProperties()                                   
                        where typeof(ICurrency).IsAssignableFrom(pi.PropertyType)
                        select pi);
    _currencyProps=currencyProps.ToArray();
}

Once you have all the PropertyInfo object you want, you can use PropertyInfo.GetValue to read a property value from a specific instance, eg :

_currencyProps[0].GetValue(rootObject);

To find all properties with values, ie not noll, you can use another query :

var values=_currencyProps.Select(pi=>new {pi.Name,Value=pi.GetValue(rootobject)})
                        .Where(val=>val.Value!=null)
                        .ToArray();

or

var values = ( from pi in _currencyProps
               let value=pi.GetValue(rootobject)
               where value !=null
               select new {pi.Name,value}
             ).ToArray();

You can create a dictionary instead of an array with ToDictionary() :

var values = ( from pi in _currencyProps
               let value=pi.GetValue(rootobject)
               where value !=null
               select new {pi.Name,Value=value}
             ).ToDictionary(pair=>pair.Name,pair=>pair.Value);

var usd=values["USD"];

Upvotes: 8

Related Questions