C# 在自引用的泛型类静态构造函数中获取类类型

C# 在自引用的泛型类静态构造函数中获取类类型,c#,generics,C#,Generics,好的,这不是一个简单的问题,代码可以帮助我解释这个问题 我需要的是一种在自引用、泛型类和静态构造函数中获取类类型的方法 假设您有这样的代码: public class ClassA : BaseClass<ClassA>{ } public abstract class BaseClass<T> where T : BaseClass<T> { static readonly int _aValue; static BaseClass(){

好的,这不是一个简单的问题,代码可以帮助我解释这个问题

我需要的是一种在自引用、泛型类和静态构造函数中获取类类型的方法

假设您有这样的代码:

public class ClassA : BaseClass<ClassA>{
}
public abstract class BaseClass<T> where T : BaseClass<T> {
    static readonly int _aValue;
    static BaseClass(){
       //here i have code that load _avalue for each kind of T type, based on my own logic
       _aValue=1;

       //need to get the real type here
    }
    public int GetValue() {
       return _aValue;
    }
}


ClassA c = new ClassA();
Console.WriteLine(c.GetValue());
这里发生的是调用静态构造函数,在我的示例中,它将值加载到静态变量

我需要知道在静态构造函数中,调用构造函数的类型(在泛型类型构造函数中,每个派生类都调用它,所以我假设我可以做我需要的事情)是否T类型实际上是ClassA

我真正需要的是知道我是否正确声明了类定义,因为我还没有找到一种好方法来确保自引用类型是真正的自引用类型,因为在我的测试中我发现了这一点

ClassX : Message<ClassAAA>
ClassX:Message
当我想强制执行时不会出现错误

ClassA : Message<ClassA>
ClassB : Message<ClassB>
ClassC : Message<ClassC>
ClassA:消息
B类:信息
C类:消息
而不是

ClassD : Message<DifferentClass>
ClassD:消息
有线索吗

我已经尝试使用MethodInfo.GetMethod().DeclaringType,但它返回基类

更新 好的,让我再解释一下 在我的场景中,我使用这种设计来定制我在客户机/服务器场景中使用的消息定义,每个不同的消息派生类必须有一个字节来指定“消息id”,因此我使用属性来装饰我的类,该属性允许我指定一个枚举值(因此代码中没有魔法数字)

在我的消息基类的静态构造函数中,我使用反射读取属性值并将其存储到其静态_aValue成员中,因此每种消息都有自己的消息id,并且出于性能原因,每个消息类型只加载一次,而不是在实例构造函数中加载。 它工作得很好,我可以说像这样的一门课

[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<PingMessage>
[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<AnotherMessage>
[MyAttribute(MyMessages.Ping)]
公共类消息:消息
每当我的PingMessage类被激活时,我就可以得到它的静态messageTye值,我对此很满意,问题是有时会发生,因为一个错误,我创建了一个类,比如

[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<PingMessage>
[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<AnotherMessage>
[MyAttribute(MyMessages.Ping)]
公共类消息:消息
泛型约束不会引起编译时错误,因为AnotherMessage是从Message继承的另一个类,所以它是合法的,但我想强制执行,如果从Message继承,则t必须是继承的类,所以只允许

PingMessage : Message<PingMessage>
PingMessage:Message 我知道没有通用约束允许我这样做,当然我也不能在约束中添加派生类,因为我不知道我将创建哪些消息(而且无论如何有很多消息是没有意义的),所以我想在消息类型的静态构造函数中进行类型约束检查,因为我已经在那里做了一些事情,所以在我看来,它是放置检查的最佳位置,如果类型没有错误或者没有在类上指定属性,就会出现异常

从技术上讲,我可以在实例构造函数中进行这种检查,但性能很重要,所以我不能


我想让我的消息实现一个自定义接口,然后让该接口的方法检查类型,并仅在初始化时调用,但我在寻找一种更简单的方法,如果可能的话,但是在这里,反射似乎帮不了我的忙

我不知道如何防止声明
class X:Message
,但是您可以将
Message
子类型的使用限制为您想要的子类型

R Foo<A>(A a) where A : Message<A>
{
  // …
}
R Foo(A)其中A:Message
{
// …
}

如果使用类型反射,则只有在运行时才能知道程序是否有效。以编译器可以检查的解决方案为目标。

我不知道有什么方法可以防止声明
class X:Message
,但是您可以将
Message
子类型的使用限制为只使用您想要的子类型

R Foo<A>(A a) where A : Message<A>
{
  // …
}
R Foo(A)其中A:Message
{
// …
}

如果使用类型反射,则只有在运行时才能知道程序是否有效。以编译器可以检查的解决方案为目标。

基类的静态构造函数在第一次访问基类时被调用。这不需要是派生类实例化,例如,在基类上调用静态方法时。派生类与基类的静态构造函数没有任何关系。它也不能,因为多个类可以从同一个泛型基类派生


派生类实例化是基类最早知道要处理哪个派生类的时间。您可以在非静态基类构造函数中测试对象的运行时类型:
如果(!typeof(T).IsAssignableFrom(this.GetType())抛出新的InvalidOperationException()。当然,缺点是它不会在编译时被捕获。

基类的静态构造函数在第一次访问基类时被调用。这不需要是派生类实例化,例如,在基类上调用静态方法时。派生类与基类的静态构造函数没有任何关系。它也不能,因为多个类可以从同一个泛型基类派生


派生类实例化是基类最早知道要处理哪个派生类的时间。您可以在非静态基类构造函数中测试对象的运行时类型:
如果(!typeof(T).IsAssignableFrom(this.GetType())抛出新的InvalidOperationException()。当然,缺点是它不能在编译时捕获。

如果(c是ClassA)
?--该示例似乎与您正在寻找的模式相匹配。您无法在静态构造函数中知道这一点,因为它是静态的,并且不会被任何类型“调用”。如果…怎么办