Ответ 1
Type objectType = myObject.GetType();
Должен все же предоставить вам конкретный тип, в соответствии с вашим примером.
Короче говоря, у меня есть функция С#, которая выполняет задачу по заданному типу, который передается как экземпляр объекта. Все работает отлично, когда экземпляр класса передается. Однако, когда объект объявлен как интерфейс, мне бы очень хотелось найти конкретный класс и выполнить действие над этим типом класса.
Вот вездесущий плохой пример (блистательный с неправильным корпусом свойств и т.д.):
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 to it и видел, что это не просто экземпляр IA, а экземпляр B, а также свойство b с помощью GetProperties(). Если я использую .GetType(), я получаю тип IA - не то, что я хочу.
Как может PerformAction определить базовый тип конкретного экземпляра IA?
У некоторых может возникнуть соблазн предложить использовать абстрактный класс, но это лишь ограничение моего плохого примера. Эта переменная будет первоначально объявлена как экземпляр интерфейса.
Type objectType = myObject.GetType();
Должен все же предоставить вам конкретный тип, в соответствии с вашим примером.
Что вы делаете, это дизайн кровати, но вам не нужно использовать отражение, которое вы можете проверить, как это.
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
}
Я должен согласиться с плохим дизайном. Если у вас есть интерфейс, это должно быть потому, что вам нужно использовать некоторые общие функции, не заботясь о том, какова конкретная реализация. Учитывая, что вы, например, похоже, что метод 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);
У вас никогда не будет экземпляров интерфейса. Поэтому определение того, имеете ли вы дело с интерфейсом или конкретным типом, невозможно, так как вы всегда будете иметь дело с конкретным типом. Поэтому я не уверен, что ваш вопрос имеет смысл. Что именно вы пытаетесь сделать и почему?
Возможно, вы ищете это оператор
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
}