代码之家  ›  专栏  ›  技术社区  ›  Marco Bettiolo

从基类的静态方法获取派生类类型

  •  17
  • Marco Bettiolo  · 技术社区  · 14 年前

    我想从基类的静态方法中获取派生类的类型。

    谢谢!

    class BaseClass {
      static void Ping () {
         Type t = this.GetType(); // should be DerivedClass, but it is not possible with a static method
      }
    }
    class DerivedClass : BaseClass {}
    
    // somewhere in the code
    DerivedClass.Ping();
    
    8 回复  |  直到 14 年前
        1
  •  17
  •   Francis Gagné    14 年前

    如果我没弄错的话 BaseClass.Ping() DerivedClass.Ping() 是相同的,因此不给方法任何参数而使其保持静态是行不通的。尝试将类型作为参数或通过泛型类型参数(可以对其强制继承约束)传递。

    class BaseClass {
        static void Ping<T>() where T : BaseClass {
            Type t = typeof(T);
        }
    }
    

    你可以这样称呼它:

    BaseClass.Ping<DerivedClass>();
    
        2
  •  37
  •   Codure    10 年前

    使用 curiously recurring template pattern

    class BaseClass<T>
        where T : BaseClass<T>
    {
        static void SomeMethod() {
            var t = typeof(T);  // gets type of derived class
        }
    }
    
    class DerivedClass : BaseClass<DerivedClass> {}
    

    调用方法:

    DerivedClass.SomeMethod();
    

    此解决方案增加了少量样板文件开销,因为必须用派生类模板化基类。

    如果您的继承树有两个以上的级别,那么它也是有限制的。在这种情况下,您必须选择是传递template参数,还是将当前类型强加给静态方法调用的子对象。

        3
  •  4
  •   Reed Copsey    14 年前

    在类型上定义了静态方法。没有“这个”。您需要将其作为实例方法:

    class BaseClass {
        public void Ping() {
            Type t = this.GetType(); // This will work, since "this" has meaning here...
        }
    

    然后您可以执行以下操作:

    class DerivedClass : BaseClass {}
    
    DerivedClass instance = new DerivedClass();
    instance.Ping();
    
        4
  •  3
  •   Community CDub    7 年前

    here . 它使用一个接口来统一所有派生类,并允许它们在不传递类型的情况下从基类调用相同的静态方法。

    public interface IDerived
    {
    }
    public class BaseClass<T> where T : IDerived
    {
        public static void Ping()
        {
            //here you have T = the derived type
        }
    }
    public class DerivedClass : BaseClass<DerivedClass>, IDerived
    {
        //with : BaseClass<DerivedClass> we are defining the T above
    }
    public class ExampleApp
    {
        public void Main()
        {
            //here we can call the BaseClass's static method through DerivedClass
            //and it will know what Type calls it
            DerivedClass.Ping();    
        }
    }
    
        5
  •  0
  •   Jürgen Steinblock    14 年前

    只是猜测(未测试)

    Type t = MethodBase.GetCurrentMethod().DeclaringType;
    
        6
  •  0
  •   mdma    14 年前

    您可以使方法成为非静态的,这样就可以通过多态性获得正确的类型,或者在子类中创建静态方法“重写”,例如。

    class DerivedClass : BaseClass
    {
       void Ping() { 
         BaseClass.Ping();
         // or alternatively
         BaseClass.Ping(Type.GetType("DerivedClass"));
       }
    }
    

    然后,您的客户机代码可以调用派生类中的方法,以显式指示它想要的是派生类版本。如果需要,还可以将DerivedClass类型作为参数传递给基类方法,以提供通过派生类调用该方法的上下文。

        7
  •  0
  •   FlyingStreudel    14 年前

    为什么不直接使用已有的方法呢?

    如果你有

    class BaseClass {}
    partial class DerivedClass : BaseClass {}
    

    你可以看看

    DerivedClass.GetType().BaseType;
    
        8
  •  0
  •   Χpẘ    11 年前

    我认为以下内容将适用于本案例(以及其他类似案例)。性能将不会太好,但如果这是罕见的,这不会是一个问题。

    在特定情况下

    $strace = (new-object diagnostics.stacktrace).tostring()
    #
    $frames = $strace -split "   at "
    $typesFromFrames = $frames | select -skip 1| # skip blank line at the beginning
       % { ($_ -split "\(",2)[0]} |                 # Get rid of parameters string
       % {$_.substring(0,$_.lastindexof("."))} |    # Get rid of method name
       $ {$_ -as [type]}
    #
    # In powershell a lot of the frames on the stack have private classes
    #  So $typesFromFrames.count is quite a bit smaller than $frames.count
    #  For the OP, I don't think this will be a problem because:
    #   1. PS isn't being used
    #   2. The derived class in the OP isn't private 
    #        (if it is then tweaks will be needed)
    #
    $derivedOnStack = $typesFromFrames | ? { $_.issubclassof( [BaseClass])}
    

    希望$derivedOnStack中只有一个元素,但这将取决于应用程序的细节。需要一些实验。