我需要的是一种在自引用类,泛型类,静态构造函数中获取类类型的方法
想象一下,你有这样的代码:
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());
然后当你做
之类的事情ClassA c = new ClassA();
Console.WriteLine(c.GetValue());
这里发生的是静态构造函数被调用,并且在我的示例中将值加载到静态变量
我需要在静态构造函数中知道,如果调用构造函数的类型(在泛型类型构造函数中,每个派生类调用它,所以我假设我可以做我需要的)如果T类型实际上是ClassA
我真正的需要是知道我是否正确地声明了我的类定义,因为我没有找到一种很好的方法来确保自引用类型是真正的自引用,因为在我的测试中我发现
ClassX : Message<ClassAAA>
在我想强制执行时不会出现错误
ClassA : Message<ClassA>
ClassB : Message<ClassB>
ClassC : Message<ClassC>
而不是
ClassD : Message<DifferentClass>
任何线索?
我已经尝试过使用MethodInfo.GetMethod()。DeclaringType但它返回基类
更新 好的,让我试着解释一下 在我的场景中,我使用这种设计来获得我在客户端/服务器场景中使用的自定义消息定义,并且每个不同的消息派生类必须有一个指定“消息ID”的字节,所以我使用属性来装饰我的类并且该属性允许我指定枚举值(所以我没有代码周围的幻数)
在我的Message基类的静态构造函数中,我使用反射来读取属性值并将其存储到其静态_aValue成员中,因此每种消息都有自己的消息ID,并且每个消息类型只加载一次,并且出于性能原因,不是在实例构造函数中。 它运作得很好,我可以说像
这样的课程[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<PingMessage>
每当我的PingMessage类被实现时,我都可以得到它的静态messageTye值,我对此很满意,问题是有时会因为错误而发生,我会创建一个像
这样的类[MyAttribute(MyMessages.Ping)]
public class PingMessage : Message<AnotherMessage>
并且泛型约束不会引起编译时错误,因为AnotherMessage是继承自Message的另一个类,因此它是合法的,但我想强制执行,如果从Message继承,则T必须是继承的类,所以只是允许
PingMessage : Message<PingMessage>
我知道没有通用约束允许我这样做,我当然不能在约束中添加派生类,因为我不知道我将创建哪些消息(并且无论如何都有很多消息它没有意义)所以我想在消息类型的静态构造函数中做我的类型约束检查,因为我已经在那里做了一些事情,所以在我看来最好放我的支票,上升如果类型没有错误或类没有指定属性
,则为例外我在技术上可以在我的实例构造函数中进行这种检查,但性能很重要所以我不能。
我想过让我的Message实现一个自定义接口然后有一个接口的方法来检查类型,并且只在初始化期间调用它,但我想找到一个更简单的方法,如果可能,但似乎反射可以'帮帮我
答案 0 :(得分:0)
我不知道如何阻止class X : Message<Y>
被声明,但您可以将Message
子类型的使用仅限于您想要的那些。
R Foo<A>(A a) where A : Message<A>
{
// …
}
如果使用类型反射,则只能在运行时知道您的程序是否有效。目标是可以由编译器检查的解决方案。
答案 1 :(得分:0)
在第一次访问基类时调用基类的静态构造函数。这不必是派生类实例化,例如,在基类上调用静态方法时。派生类与基类的静态构造函数无关。也不可能,因为多个类可以从相同的通用基类派生。
派生类实例化是基类可以知道您正在处理哪个派生类的最早时间。您可以在非静态基类构造函数中测试对象的运行时类型:if (!typeof(T).IsAssignableFrom(this.GetType())) throw new InvalidOperationException();
。当然,缺点是它在编译时没有被捕获。