查找接口实例背后的具体类型

Posted

技术标签:

【中文标题】查找接口实例背后的具体类型【英文标题】:Finding the Concrete Type behind an Interface instance 【发布时间】:2010-11-12 16:38:48 【问题描述】:

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

这是一个普遍存在的坏例子(带有错误的属性大小写等):

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 中的代码对其参数使用反射,并看到它不仅是 IA 的实例,而且是 B 的实例,并通过 GetProperties() 查看属性“b”。如果我使用 .GetType() 我会得到 IA 的类型 - 这不是我想要的。

PerformAction 如何确定 IA 实例的底层具体类型?

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

【问题讨论】:

【参考方案1】:

您永远不能拥有接口的实例。因此,确定您是在处理接口还是具体类型是不可能的,因为您将始终处理具体类型。所以我不确定你的问题是否有意义。你到底想做什么,为什么?

【讨论】:

【参考方案2】:

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

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】:
Type objectType = myObject.GetType();

根据您的示例,仍应为您提供具体类型。

【讨论】:

是的,调用“myObject.GetType()”永远不会返回接口类型。 PerfomAction的参数是object,但是他不能这样做:例如IA.getType()【参考方案4】:

也许您正在寻找is operator

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

【讨论】:

您正在投射两次。直接使用as 运算符并稍后检查是否为空【参考方案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);

【讨论】:

以上是关于查找接口实例背后的具体类型的主要内容,如果未能解决你的问题,请参考以下文章

Unity - 组件类型和实例的混淆

MySQL索引背后的数据结构及算法原理(employees实例)

初识Java集合及包装类和泛型的基本使用

laravel的Facades外观模式背后实现原理

laravel的Facades外观模式背后实现原理

selenium 元素查找背后的属性