【发布时间】:2016-05-02 07:13:23
【问题描述】:
好的,这不是一个简单的问题,代码将帮助我解释问题。
我需要的是一种在自引用、泛型类、静态构造函数中获取类类型的方法
想象一下你有这样的代码:
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 成员中,因此每种 Message 都有自己的消息 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 实现一个自定义接口,然后使用该接口的方法来检查类型,并仅在初始化期间调用它,但如果可能的话,我一直在寻找一种更简单的方法,但似乎反射可以'在这里帮不了我
【问题讨论】:
-
if (c is ClassA)? MSDN -- 该示例似乎与您正在寻找的模式相匹配。 -
您无法在静态构造函数中知道这一点,因为它是静态的,不会被任何类型“调用”。如果您在实例构造函数中执行此操作并在类不是自引用的情况下抛出异常怎么办?
-
你能解释一下为什么你需要在静态构造函数而不是实例构造函数中这样做吗?
-
请注意
BaseClass<X>的静态构造函数对于派生自BaseClass<X>的所有类只会被调用一次。例如,如果您有ClassB : BaseClass<ClassA>和ClassA : BaseClass<ClassA>,那么静态构造函数将只针对这两种类型一起执行一次。 -
添加了更新以更好地解释问题以及为什么建议的答案不适用