查找Interface实例后面的具体类型

44 c# types interface concrete

简而言之,我有一个C#函数,它对作为Object实例传入的给定Type执行任务.传入类实例时,一切正常.但是,当对象被声明为接口时,我真的很想找到具体的类并对该类类型执行操作.

这是无处不在的坏例子(金属外壳不正确等等):

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
}
Run Code Online (Sandbox Code Playgroud)

我希望PerformAction中的代码使用Reflection来反对它的参数,看看它不仅仅是IA的一个实例,而是它的B实例,并通过GetProperties()查看属性"b".如果我使用.GetType(),我会得到IA的类型 - 而不是我想要的.

PerformAction如何确定IA实例的基础Concrete Type?

有些人可能会建议使用Abstract类,但这只是我的坏例子的限制.该变量最初将被声明为接口实例.

Sta*_* R. 76

Type objectType = myObject.GetType();
Run Code Online (Sandbox Code Playgroud)

根据你的例子,还应该给你具体的类型.

  • 是的,调用"myObject.GetType()"将永远不会返回接口类型. (2认同)

Ars*_*yan 5

你在做什么是真正的床设计,但你不必使用反射,你可以像这样检查它

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
}
Run Code Online (Sandbox Code Playgroud)

  • 这仍然是相当糟糕的设计,因为您仍然依赖于具体类型.这在很大程度上违背了首先拥有界面的目的...... (2认同)

jri*_*sta 5

我必须同意糟糕的设计.如果你有一个接口,应该是因为你需要利用一些常见的功能而不关心具体的实现.举个例子,听起来像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);
Run Code Online (Sandbox Code Playgroud)