Нахождение конкретного типа за экземпляром интерфейса - PullRequest
42 голосов
/ 21 июля 2009

Короче говоря, у меня есть функция C #, которая выполняет задачу с данным типом, который передается как экземпляр объекта. Все работает нормально, когда передается экземпляр класса. Однако, когда объект объявлен как интерфейс, я действительно хотел бы найти конкретный класс и выполнить действие над этим типом класса.

Вот вездесущий плохой пример (великолепный с неправильным регистром свойств и т. Д.):

public interface IA
{
    int a { get; set; }
}
public class B : IA
{
    public int a { get; set; }
    public int b { get; set; }
}
public class C : IA
{
    public int a { get; set; }
    public int c { get; set; }
}

// snip

IA myBObject = new B();
PerformAction(myBObject);

IA myCObject = new C();
PerformAction(myCObject);

// snip

void PerformAction(object myObject)
{
    Type objectType = myObject.GetType();   // Here is where I get typeof(IA)
    if ( objectType.IsInterface )
    {
        // I want to determine the actual Concrete Type, i.e. either B or C
        // objectType = DetermineConcreteType(objectType);
    }
    // snip - other actions on objectType
}

Я бы хотел, чтобы код в PerformAction использовал Reflection против своего параметра и увидел, что это не просто экземпляр IA, но что это экземпляр B, и чтобы видеть свойство "b" через GetProperties (). Если я использую .GetType (), я получаю тип IA - не то, что я хочу.

Как PerformAction может определить базовый конкретный тип экземпляра IA?

У некоторых может возникнуть соблазн предложить использовать класс Abstract, но это только ограничение моего плохого примера. Переменная будет первоначально объявлена ​​как экземпляр интерфейса.

Ответы [ 5 ]

72 голосов
/ 21 июля 2009
Type objectType = myObject.GetType();

Должен все же дать вам конкретный тип, в соответствии с вашим примером.

5 голосов
/ 22 июля 2009

Я должен согласиться с плохим дизайном. Если у вас есть интерфейс, это должно быть потому, что вам нужно использовать некоторые общие функции, не заботясь о том, что такое конкретная реализация. Учитывая ваш пример, похоже, что метод PerformAction должен быть частью интерфейса:

public interface IA
{
    int a { get; set; }
    void PerformAction();
}

public class B: IA
{
    public int a { get; set; }
    public int b { get; set; }

    public void PerformAction()
    {
        // perform action specific to B
    }
}

public class C : IA
{
    public int a { get; set; }
    public int c { get; set; }

    public void PerformAction()
    {
        // perform action specific to C
    }
}

void PerformActionOn(IA instance)
{
    if (instance == null) throw new ArgumentNullException("instance");

    instance.PerformAction();

    // Do some other common work...
}


B b = new B();
C c = new C();

PerformActionOn(b);
PerformActionOn(c);
5 голосов
/ 21 июля 2009

Что вы делаете, так это дизайн кровати, но вам не нужно использовать отражение, вы можете проверить это следующим образом

void PerformAction(object myObject)
{
    B objectType = myObject as B;   // Here is where I get typeof(IA)
    if ( objectType != null )
    {
        //use objectType.b
    }
    else
    {
       //Same with A 
    }
    // snip - other actions on objectType
}
3 голосов
/ 21 июля 2009

Вы никогда не можете иметь экземпляры интерфейса. Поэтому определить, имеете ли вы дело с интерфейсом или конкретным типом, невозможно, поскольку вы всегда будете иметь дело с конкретным типом. Поэтому я не уверен, что ваш вопрос имеет какой-либо смысл. Что именно вы пытаетесь сделать и почему?

1 голос
/ 22 июля 2009

Может быть, вы ищете оператор

void PerformAction(object myObject)
{
    if (myObject is B)
    {
        B myBObject = myObject as B;
        myBObject.b = 1;
    }

    if (myObject is C)
    {
        C myCObject = myObject as C;
        myCObject.c = 1;
    }

    // snip - other actions on objectType
}
...