【问题标题】: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 类,但这只是我的坏例子的限制。该变量最初将被声明为接口实例。

【问题讨论】:

    标签: c# interface types concrete


    【解决方案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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 2021-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        相关资源
        最近更新 更多