.NET:在其静态方法中确定“this”类的types
在一个非静态的方法,我可以使用this.GetType()
,它会返回Type
。 我怎样才能获得相同的Type
在一个静态的方法? 当然,我不能只写typeof(ThisTypeName)
因为ThisTypeName
只在运行时才是已知的。 谢谢!
如果您正在寻找与静态方法的this.GetType()
等效的1 this.GetType()
,请尝试以下操作。
Type t = MethodBase.GetCurrentMethod().DeclaringType
虽然这可能比仅使用typeof(TheTypeName)
要昂贵得多。
还有一些其他的答案还没有完全弄清楚,哪一个和你的types的思想只有在执行时才有用。
如果使用派生types来执行静态成员,则在二进制文件中省略实际types名称。 所以例如,编译这个代码:
UnicodeEncoding.GetEncoding(0);
现在使用ildasm …你会看到这样的呼叫:
IL_0002: call class [mscorlib]System.Text.Encoding [mscorlib]System.Text.Encoding::GetEncoding(int32)
编译器已经解决了对Encoding.GetEncoding
的调用 – 没有剩下UnicodeEncoding
的痕迹。 恐怕,这使得你的“现有types”的想法是荒谬的。
另一个解决scheme是使用自适应types
//My base class //I add a type to my base class use that in the static method to check the type of the caller. public class Parent<TSelfReferenceType> { public static Type GetType() { return typeof(TSelfReferenceType); } }
然后在inheritance它的类中,我创build一个自引用types:
public class Child: Parent<Child> { }
现在Parent中的调用typestypeof(TSelfReferenceType)将获得并返callback用者的Type而不需要实例。
Child.GetType();
-抢
你不能在静态方法中使用this
,所以这是不可能的。 但是,如果您需要某个对象的types,只需调用GetType
并使this
实例成为必须传递的参数,例如:
public class Car { public static void Drive(Car c) { Console.WriteLine("Driving a {0}", c.GetType()); } }
不过这似乎是一个糟糕的devise。 你确定你真的需要在自己的静态方法中获取实例本身的types吗? 这似乎有点奇怪。 为什么不使用实例方法?
public class Car { public void Drive() { // Remove parameter; doesn't need to be static. Console.WriteLine("Driving a {0}", this.GetType()); } }
我不明白你为什么不能使用typeof(ThisTypeName)。 如果这是一个非genericstypes,那么这应该工作:
class Foo { static void Method1 () { Type t = typeof (Foo); // Can just hard code this } }
如果它是一个genericstypes,那么:
class Foo<T> { static void Method1 () { Type t = typeof (Foo<T>); } }
我在这里错过了很明显的东西吗
当你的成员是静态的,你将永远知道它在运行时是什么types的。 在这种情况下:
class A { public static int GetInt(){} } class B : A {}
你不能打电话(编辑:显然,你可以看到下面的评论,但你仍然会打电话给A):
B.GetInt();
因为成员是静态的,所以在inheritance场景中不起作用。 埃尔戈,你总是知道这个types是A.
为了我的目的,我喜欢@T-moty的想法。 尽pipe我多年来一直使用“自引用types”信息,但引用基类很难做到。
例如(使用上面的@Rob Leclerc例子):
public class ChildA: Parent<ChildA> { } public class ChildB: Parent<ChildB> { }
例如,使用这种模式可能是有挑战性的。 你如何从函数调用返回基类?
public Parent<???> GetParent() {}
或者当types铸造?
var c = (Parent<???>) GetSomeParent();
所以,我尽量避免它,当我必须使用它。 如果你一定要,我build议你遵循这种模式:
class BaseClass { // All non-derived class methods goes here... // For example: public int Id { get; private set; } public string Name { get; private set; } public void Run() {} } class BaseClass<TSelfReferenceType> : BaseClass { // All derived class methods goes here... // For example: public TSelfReferenceType Foo() {} public void Bar(TSelfRefenceType obj) {} }
现在,您可以(更)轻松地使用BaseClass
。 但是,像我目前的情况一样,有时候不需要从基类中暴露派生类,使用@M-moty的build议可能是正确的方法。
但是,只要基类不包含调用堆栈中的任何实例构造函数,就只能使用@M-moty的代码。 不幸的是我的基类使用实例构造函数。
因此,这是我的扩展方法,考虑到基类的“实例”构造函数:
public static class TypeExtensions { public static Type GetDrivedType(this Type type, int maxSearchDepth = 10) { if (maxSearchDepth < 0) throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0."); const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor. var stack = new StackTrace(); var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount); var frame = skipFrames; // Skip all the base class 'instance' ctor calls. // while (frame < maxCount) { var method = stack.GetFrame(frame).GetMethod(); var declaringType = method.DeclaringType; if (type.IsAssignableFrom(declaringType)) return declaringType; frame++; } return null; } }
编辑这个方法只有当你用可执行文件/库部署PDB文件时才有效,就像markmnl指出的那样。
否则将会是一个很大的问题:在开发中运行良好,但可能不在生产中。
实用程序方法,只需在代码的每个位置调用需要的方法即可:
public static Type GetType() { var stack = new System.Diagnostics.StackTrace(); if (stack.FrameCount < 2) return null; return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType; }