确定一个类型是否为静态

45

假设我有一个名为typeType

我想确定是否可以使用我的类型来执行以下操作(而不实际对每个类型执行此操作):

如果typeSystem.Windows.Point,那么我可以这样做:

Point point1 = new Point();

然而,如果typeSystem.Environment,则以下代码将无法正常运行:

Environment environment1 = new Environment(); //wrong

如果我要迭代一个程序集中所有可见的类型,如何跳过那些无法创建实例的类型,比如第二个类型?我对反射还不是很熟悉,术语也不是很清楚。希望我的意思表达得够清楚。

5个回答

94

static类在IL级别上被声明为abstractsealed。因此,您可以检查IsAbstract属性以一次处理abstract类和static类(对于您的用例)。

但是,abstract类不是您无法直接实例化的唯一类型。您应该检查诸如接口(不带CoClass属性)和没有由调用代码访问的构造函数的类型等内容。


27
type.IsAbstract && type.IsSealed

对于 C# 来说,这将是一个足够的检查,因为在 C# 中,抽象类不能被声明为 sealed 或 static。然而,当处理来自其他语言的 CLR 类型时,需要小心。


7
你可以这样搜索公共构造函数:
Type t = typeof(Environment);
var c = t.GetConstructors(BindingFlags.Public);
if (!t.IsAbstract && c.Length > 0)
{
     //You can create instance
}

如果您只对无参构造函数感兴趣,您可以使用

Type t = typeof(Environment);
var c = t.GetConstructor(Type.EmptyTypes);
if (c != null && c.IsPublic && !t.IsAbstract )
{
     //You can create instance
}

2
请注意,一个抽象类可以有一个公共构造函数。你不能在if语句的主体中创建一个类的实例。你会得到MemberAccessException异常。 - Mehrdad Afshari

1
Type t = typeof(System.GC);
Console.WriteLine(t.Attributes);
TypeAttributes attribForStaticClass = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class |
TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit;
Console.WriteLine((t.Attributes == attribForStaticClass));

我猜,这应该可以工作。


我认为唯一适用于静态类的是 TypeAttributes.BeforeFieldInit -- 这是我用来确定静态类的方法。检查 IsAbstractIsSealed 也可以保证只有静态类型,但这需要更多的检查。 - mhand

-4
这是一种获取程序集中所有类型的所有公共构造函数的方法。
    var assembly = AppDomain.CurrentDomain.GetAssemblies()[0]; // first assembly for demo purposes
var types = assembly.GetTypes();
foreach (var type in types)
{
    var constructors = type.GetConstructors();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接