Доступ к собственности Generi c без общего базового класса - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть два независимых класса библиотеки, у которых нет одинакового базового класса, и я не могу изменить реализацию этих классов.

Представьте, что классы выглядят так:

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

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

Теперь я хочу создать обобщенный класс c, который зависит от A или B и получить доступ к значению X.

Итак, я сделал:

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

Если бы я реализовал A и B на себе, я бы определил интерфейс, который реализует свойство X, но я не могу этого сделать. Есть ли другой способ, не меняя класс A и B, сказать, что Generi c T имеет свойство X?
Другая идея - сделать дочерние классы A и B, которые затем реализуют упомянутый интерфейс, но я хочу этого избежать.

Ответы [ 2 ]

5 голосов
/ 01 апреля 2020

Вы можете перегрузить Foo, чтобы получить либо A, либо B:

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

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

Если вы хотите сделать это для каждого мыслимого класса, который может иметь свойство X, тогда вы ' Вам понадобится решение на основе отражения. Например:

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

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

ПРИМЕЧАНИЕ. Я минимизировал обработку ошибок здесь. Вам нужно будет обработать случай, когда свойство может не иметь геттера (редко) или когда оно не возвращает int

Если количество классов является управляемым, то вы можете создать интерфейс с свойство, получить новый класс и реализовать интерфейс, который не потребует изменения. Например:

interface IMyStuff
{
  int X{get;}
}

class MyA : A, IMyStuff
{
}

class MyB : B, IMyStuff
{
}

Foo не может принять интерфейс:

void Foo(IMyStuff stuff)
{
  int x = stuff.X
}
2 голосов
/ 01 апреля 2020

Другой вариант - использовать 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, по существу, реализующий «типизацию утки»: если dynamic объект g имеет свойство X, то g.X получит это. Это альтернатива реализации отражения вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...