.NET : 정적 메서드에서 "this"클래스 유형 확인
비 정적 메서드에서 사용할 수 this.GetType()
있으며 Type
. Type
정적 메서드에서 어떻게 똑같이 얻을 수 있습니까? 물론 런타임에서만 알려져 typeof(ThisTypeName)
있기 때문에 그냥 쓸 수는 없습니다 ThisTypeName
. 감사!
this.GetType()
정적 메서드에 해당하는 1 라이너를 찾고 있다면 다음을 시도하십시오.
Type t = MethodBase.GetCurrentMethod().DeclaringType
.NET을 사용하는 것보다 훨씬 비쌉니다 typeof(TheTypeName)
.
다른 답변이 명확하지 않은 것이 있으며 실행 시간에만 사용할 수있는 유형에 대한 아이디어와 관련이 있습니다.
파생 형식을 사용하여 정적 멤버를 실행하는 경우 이진에서 실제 형식 이름이 생략됩니다. 예를 들어 다음 코드를 컴파일하십시오.
UnicodeEncoding.GetEncoding(0);
이제 ildasm을 사용하십시오 ... 호출이 다음과 같이 방출되는 것을 볼 수 있습니다.
IL_0002: call class [mscorlib]System.Text.Encoding
[mscorlib]System.Text.Encoding::GetEncoding(int32)
컴파일러가에 대한 호출을 해결했습니다 . 남은 Encoding.GetEncoding
흔적이 없습니다 UnicodeEncoding
. 그것은 "현재 유형"에 대한 당신의 생각을 무의미하게 만듭니다.
또 다른 해결책은 자기 참조 유형을 사용하는 것입니다.
//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);
}
}
그런 다음 상속하는 클래스에서 자체 참조 유형을 만듭니다.
public class Child: Parent<Child>
{
}
이제 Parent 내부의 호출 유형 typeof (TSelfReferenceType)는 인스턴스 없이도 호출자의 유형을 가져와 반환합니다.
Child.GetType();
-롭
this
정적 메서드에서는 사용할 수 없으므로 직접 가능하지 않습니다. 그러나 어떤 객체의 유형이 필요한 경우 해당 객체를 호출 GetType
하고 this
인스턴스를 전달해야하는 매개 변수로 만듭니다. 예 :
public class Car {
public static void Drive(Car c) {
Console.WriteLine("Driving a {0}", c.GetType());
}
}
그러나 이것은 형편없는 디자인처럼 보입니다. 자체 정적 메서드 내에서 인스턴스 자체의 유형을 실제로 가져와야합니까? 좀 이상해 보입니다. 인스턴스 메서드를 사용하지 않는 이유는 무엇입니까?
public class Car {
public void Drive() { // Remove parameter; doesn't need to be static.
Console.WriteLine("Driving a {0}", this.GetType());
}
}
typeof (ThisTypeName)을 사용할 수없는 이유를 이해할 수 없습니다. 이것이 제네릭이 아닌 유형이면 작동합니다.
class Foo {
static void Method1 () {
Type t = typeof (Foo); // Can just hard code this
}
}
제네릭 유형 인 경우 :
class Foo<T> {
static void Method1 () {
Type t = typeof (Foo<T>);
}
}
여기서 분명한 것이 누락 되었습니까?
멤버가 정적 인 경우 런타임에 어떤 유형의 일부인지 항상 알 수 있습니다. 이 경우 :
class A
{
public static int GetInt(){}
}
class B : A {}
전화를 걸 수 없습니다 (편집 : 분명히 아래 주석을 볼 수 있지만 여전히 A로 전화를 걸 것입니다) :
B.GetInt();
멤버가 정적이기 때문에 상속 시나리오에서 역할을하지 않습니다. Ergo, 당신은 항상 유형이 A라는 것을 알고 있습니다.
For my purposes, I like @T-moty's idea. Even though I have used "self-referencing type" information for years, referencing the base class is harder to do later.
For example (using @Rob Leclerc example from above):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Working with this pattern can be challenging, for example; how do you return the base class from a function call?
public Parent<???> GetParent() {}
Or when type casting?
var c = (Parent<???>) GetSomeParent();
So, I try to avoid it when I can, and use it when I must. If you must, I would suggest that you follow this pattern:
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) {}
}
Now you can (more) easily work with the BaseClass
. However, there are times, like my current situation, where exposing the derived class, from within the base class, isn't needed and using @M-moty's suggestion just might be the right approach.
However, using @M-moty's code only works as long as the base class doesn't contain any instance constructors in the call stack. Unfortunately my base classes do use instance constructors.
Therefore, here's my extension method that take into account base class 'instance' constructors:
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;
}
}
EDIT This methods will works only when you deploy PDB files with the executable/library, as markmnl pointed out to me.
Otherwise will be a huge issue to be detected: works well in developement, but maybe not in production.
Utility method, simply call the method when you need, from every place of your code:
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;
}
'programing tip' 카테고리의 다른 글
프로젝트 기타 파일에 대한 NuGet 패키지 복원 실패 : 값은 null이거나 빈 문자열 일 수 없습니다. (0) | 2020.09.09 |
---|---|
Google 크롬에서 기본 날짜 선택기 비활성화 (0) | 2020.09.09 |
파이썬의 사전에서 속성 설정 (0) | 2020.09.09 |
IIS : 유휴 시간 초과 대 재활용 (0) | 2020.09.08 |
TypeScript를 사용하여 Angular2의 http 데이터에서 RxJS Observables 연결 (0) | 2020.09.08 |