RoQuOTriX
RoQuOTriX

Reputation: 3001

Access Property of Generic without common base class

I have two independent classes of a library which doesn't have the same base class, neither I can change the implementation of this classes.

Imagine the classes look like this:

public class A {
     public int X { get; } = 1;
}

public class B {
     public int X { get; } = 2;
}

Now I want to create a generic class, which is either depending on A or on B and access the value of X in there.

So i did:

public class GenericClass<T> 
    /*where T : ?*/
{
    void Foo(T t) {
        int x = t.X; // is this possible and how? 
    }
}

If I would implement A and B on myself, I would define an Interface which implements the Property X, but I can't do this. Is there any other way, without changing class A and B, to say that the Generic T has the Property X?
Another idea would be to make child classes of A and B which then implement the mentioned Interface, but I want to avoid this.

Upvotes: 0

Views: 182

Answers (2)

printf
printf

Reputation: 335

Another option is to use dynamic.

dynamic d;
d = t;         // here t can be an instance of A, or or B, or of anything that has X
int x = d.X;

dynamic essentially implements "duck typing": if a dynamic object g has a property X, then g.X will retrieve it. This is an alternative to implementing reflection manually.

Upvotes: 2

Sean
Sean

Reputation: 62472

You can overload Foo to take either A or B:

void Foo(A t)
{
  int x = t.X;
}

void Foo(B t)
{
  int x = t.X;
}

If you want to do it for every conceivable class that might have an X property then you'll need a reflection based solution. For example:

void Foo(object obj)
{
  var property = obj.GetType().GetProperty("X");
  if(property == null) throw new Exception();

  int x = (int)property.GetValue(obj);
}

NOTE: I've minimized the error handling here. You'd need to handle the case where the property might not have a getter (rare) or where it doesn't return an int

If the number of classes is manageable then you could create an interface with the property, derive a new class and implement the interface, which won't require a change. For example:

interface IMyStuff
{
  int X{get;}
}

class MyA : A, IMyStuff
{
}

class MyB : B, IMyStuff
{
}

Not you can have Foo accept the interface:

void Foo(IMyStuff stuff)
{
  int x = stuff.X
}

Upvotes: 5

Related Questions