tags:

views:

51

answers:

2

I have three classes: SomeThing, SomeOtherThing, and YetAntherThing. All three have an identical member called Properties. In each class, it is a key/value pair such that I can reference obj1.Name, obj1.Value, obj2.Name, obj2.Value, obj3.Name, and obj3.Value. I'd like to pass these three objects into a single method that could iterate through their respective "Properties" collections without having to know at compile time which it was operating on. I envision something like:

SomeThing obj1;
SomeOtherThing obj2;
YetAntherThing obj3;

DoProperties( obj1, obj1.GetType() );
DoProperties( obj2, obj2.GetType() );
DoProperties( obj3, obj3.GetType() );

...

private void DoProperties( object obj, Type objectType )
{
    // this is where I get lost. I want to "cast" 'obj' to the type
    // held in 'objectType' so that I can do something like:
    //
    // foreach ( var prop in obj.Properties )
    // {
    //    string name = prop.Name;
    //    string value = prop.Value;
    // }
}

Note: The classes SomeThing, SomeOtherThing, and YetAntherThing are defined externally, I have no control over them or access to their source code, and they are all sealed.

+7  A: 

You've got two options; either get each class to implement an interface that exposes the collection, eg:

interface IHasProperties
{
    PropertyCollection Properties {get;}
}

Then declare your method, referencing that interface:

private void DoProperties(IHasProperties obj)
{
    foreach (var prop in obj.Properties)
    {
        string name = prop.Name;
        string value = prop.Value;
    }
}

Or use reflection to look-up the Properties collection at run-time, e.g.:

private void DoProperties(object obj)
{
    Type objectType = obj.GetType();

    var propertyInfo = objectType.GetProperty("Properties", typeof(PropertyCollection));

    PropertyCollection properties = (PropertyCollection)propertyInfo.GetValue(obj, null);

    foreach (var prop in properties)
    {
        //    string name = prop.Name;
        //    string value = prop.Value;
    }
}
FacticiusVir
The solution using reflection was just the ticket. Thanks!
BillP3rd
+2  A: 

The interface mentioned by FacticiusVir is the way to go, if you have control over the source of each object. Absent that, there is a third option in .NET 4. dynamic.

Given

class A
{
    public Dictionary<string, string> Properties { get; set; }
}

class B
{
    public Dictionary<string, string> Properties { get; set; }
}

class C
{
    public Dictionary<string, string> Properties { get; set; }
}

You can accept the parameter as type dynamic and your code will compile (and bomb at runtime if it is not valid).

static void DoSomething(dynamic obj)
{
    foreach (KeyValuePair<string, string> pair in obj.Properties)
    {
        string name = pair.Key;
        string value = pair.Value;
        // do something
    }
}
Anthony Pegram