如何使用.NET中的反射来确定和检查程序集中的类型是自定义类型还是基元类型?

时间:2010-09-04 15:12:14

标签: c# reflection .net-4.0

是否可以在运行时检查给定类型是自定义数据类型还是.NET的原始数据类型之一?

我在程序集中定义了用户定义的类型,所有类型都是一些结构。我需要调用用户定义类型的方法,其中的参数是那些结构。因此,在使用反射在运行时调用这些函数之前,需要相应地填充数据。

现在是否有任何反射方法可用于跟踪给定数据类型是自定义数据类型还是原始数据类型。我知道IsClass属性,但我的目标用户定义数据类型不是类,这些公共是STRUCTS。

7 个答案:

答案 0 :(得分:8)

我会选择类似的东西:

static bool IsFundamental(this Type type)
{
    return type.IsPrimitive || type.Equals(typeof(string)) || type.Equals(typeof(DateTime));
}

选择stringDateTime作为the types for which IsPrimitive returns true的补充,是一个主观问题,因为没有绝对列表......最终的选择是你的(你可能想要的)例如,也包括decimal;它应该明确记录(至少在评论中,最好是XML文件)。

答案 1 :(得分:4)

根据此question中的信息,您可以使用以下代码完成此操作:

public static class TypeExtensions
{
    private static List<byte[]> tokens = new List<byte[]>() 
    {
        new byte[] {0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89},
        new byte[] {0x31, 0xbf, 0x38, 0x56, 0xad, 0x36, 0x4e, 0x35},
        new byte[] {0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a}
    };

    public static bool IsFrameworkType(this Type type)
    {
        if (type == null) { throw new ArgumentNullException("type"); }

        byte[] publicKeyToken = type.Assembly.GetName().GetPublicKeyToken();    

        return publicKeyToken != null && publicKeyToken.Length == 8
           && tokens.Contains(publicKeyToken, new ByteArrayEqualityComparer());
    }
}

公钥标记集对.NET 2.0及更高版本(包括.NET 4.0)有效。 ByteArrayEqualityComparer类看起来像:

public class ByteArrayEqualityComparer : EqualityComparer<byte[]>
{
    public override bool Equals(byte[] x, byte[] y)
    {
        return x != null && y != null
                    && x.Length == 8 && y.Length == 8
                    && x[0] == y[0]
                    && x[1] == y[1]
                    && x[2] == y[2]
                    && x[3] == y[3]
                    && x[4] == y[4]
                    && x[5] == y[5]
                    && x[6] == y[6]
                    && x[7] == y[7];
    }

    public override int GetHashCode(byte[] obj)
    {
        return obj.GetHashCode();
    }
}

然后您将使用此方法:

Debug.WriteLine("Is type `string` a .NET Framework type? {0}",
   typeof(string).IsFrameworkType());

答案 2 :(得分:1)

答案 3 :(得分:0)

确定BCL / CLR是否提供类型的一种非常简单的基本方法是:

var type = typeof(int);
var isSystemType = type.Assembly.FullName.StartsWith("mscorlib");

请注意,使用Type.IsPrimitive会为System.String返回 false ,因此它取决于您使用的“原始”的定义是否合适或不

答案 4 :(得分:0)

听起来你需要区分你自己制作的其他类型。只需创建一个自定义属性,放在每个类型上,如下所示:

[CustomAttribute]
struct MyDataType
{
....
}

另一个选择是创建一个所有自定义类型实现的接口。然后,通过执行if (x is ICustom) ...,您很容易看到是否需要对该实例执行一些特殊操作。

如果可以将它们全部放在同一个命名空间或程序集中,那么这些也很容易用反射来检查。

答案 5 :(得分:0)

您可以通过检查类型或程序集的全名来实现,如下所示

if(obj.GetType().Assembly.FullName.Contains("MyAssembly"))
{
    //User-defined type
}
else if(obj.GetType().FullName.StartsWith("System."))
{
    //.NET type
}

答案 6 :(得分:0)

我遵循的最简单方法是验证命名空间,以确定它是否是您的自定义类型之一。例如,您的命名空间可能是“YourCompany.YourDepartment”,可以根据类型的命名空间进行验证。