【问题标题】:Get derived type from static method从静态方法获取派生类型
【发布时间】:2013-01-10 15:06:18
【问题描述】:

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

我想做这样的事情

void foo()
{
  this.getType();
}

但在静态方法中

我知道

MethodBase.GetCurrentMethod().DeclaringType

返回基本类型,但我需要派生。

【问题讨论】:

  • 你能举个更详细的例子吗?
  • 顺便说一句,“sth”不是英文单词,也不是“something”这个词的公认缩写。

标签: c# reflection types static


【解决方案1】:

假设你的意思是你有这样的东西

class MyBaseClass
{
    public static void DoSomething()
    {
        Console.WriteLine(/* current class name */);
    }
}

class MyDerivedClass : MyBaseClass
{
}

又想让MyDerivedClass.DoSomething();打印"MyDerivedClass",那么答案是:

您的问题没有解决方案。静态方法不像实例方法那样被继承。您可以使用MyBaseClass.DoSomethingMyDerivedClass.DoSomething 引用DoSomething,但两者都编译为对MyBaseClass.DoSomething 的调用。无法找出源代码中使用了哪个来进行调用。

【讨论】:

  • 我认为如果 FxCop 或 ReSharper 发现你在派生类上调用静态方法时会抱怨——比如“你确定你知道这里发生了什么吗?”
  • 所以,我大概应该使用 Generic,并尝试获取 typeof(T),或者你知道有什么更好的方法吗?
  • 您可以将类型传递给方法:DoSomething(Type derivedStaticType),然后在 DoSomething 内部使用此类型(同时检查它是否确实从 MyBaseClass 派生)。有点难看,但它的工作原理。
  • 在 java 中,您可以通过 stacktrace hack 获取调用类,但我认为这在 C# 中是不可能的。
【解决方案2】:

我猜你需要这样的场景:

void Main()
{
  Base.StaticMethod(); // should return "Base"
  Derived.StaticMethod();  // should return "Derived"
}


class Base
{
  public static void StaticMethod()
  {
    Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
  }
}

class Derived: Base 
{
}

但是,此代码将返回

Base       
Base

这是因为静态方法调用在编译时被解析为对基类的调用,基类实际上定义了它,即使它是从派生类调用的。线条

Base.StaticMethod();
Derived.StaticMethod();

生成以下 IL:

IL_0001:  call        Base.StaticMethod
IL_0006:  nop         
IL_0007:  call        Base.StaticMethod

一句话,做不到。

【讨论】:

    【解决方案3】:

    7 1/2 年后...

    我非常想做同样的事情,这就是我发现这个问题的方式。有一个与所要求的内容接近的解决方案,可能对其他搜索此问题的人有用。

    我想要一个静态方法,它会返回一个类的实例,其中包含为我设置的所有基本设置。以下作品:

    void Main()
    {
        ChildClassA cA = ChildClassA.SetFoo();
    }
    
    public abstract class BaseClass
    {
        public bool Foo {get; set;}
    }
    
    public class ChildClassA : BaseClass
    {
        public static ChildClassA SetFoo() => new ChildClassA{Foo = false};
    }
    
    public class ChildClassB : BaseClass
    {
        public static ChildClassB SetFoo() => new ChildClassB { Foo = false };
    }
    

    这一切都很好,但我想将 SetFoo 函数放在基类中,以便

    1. 我不必有那么多重复的代码和
    2. 确保所有 BaseClass 对象都有SetFoo

    你不能这样做:

        public abstract static BaseClass SetFoo;
    

    因为静态的东西不可能是抽象的。你也不能这样做:

        public static BaseClass SetFoo => new BaseClass{ Foo = false };
    

    因为你不能新建一个抽象类。

    不过,您可以做的是使用泛型来指定您想要的派生类型。看起来像这样:

    void Main()
    {
        ChildClassA cA = BaseClass.SetFoo<ChildClassA>();
    }
    
    public abstract class BaseClass
    {
        public bool Foo {get; set;}
        
        public static T SetFoo<T>() where T:BaseClass, new() => new T{Foo = false };
    }
    
    public class ChildClassA : BaseClass
    {
        // You can leave this here if you still want to call ChildClassA.SetFoo();
        //public static ChildClassA SetFoo() => new ChildClassA{Foo = false};
    }
    
    public class ChildClassB : BaseClass
    {
        //Again, you can leave this for ChildClassB.SetFoo()--the compiler won't mind
        //public static ChildClassB SetFoo() => new ChildClassB { Foo = false };
    }
    

    这只是比我们真正想要的(派生的.StaticBase)稍微笨拙一点,但非常接近。

    【讨论】:

      猜你喜欢
      • 2011-03-05
      • 2012-05-24
      • 2010-09-22
      • 2015-04-08
      • 2011-02-24
      • 2013-04-24
      • 2019-08-23
      • 2010-10-10
      相关资源
      最近更新 更多