简体   繁体   中英

How to determine and check whether a type in assembly is Custom type or Primitive type using reflection in .NET?

Is it possible to check at runtime whether given type is Custom data type or one of primitive data types of .NET?

I have defined user defined types in assembly and those all types are some structs. I need to call the methods of user defined types of whome parameters are those structs. So this needs to fill the data accordingly before calling those function at runtime using reflection.

Now Is there any method available in reflection by which we can track that given data type is custom or primitive data type. I know about IsClass attribute, but my targeted user defined data types are not classes , these public are STRUCTS.

I'd go with something like:

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

The choice of string and DateTime as additions to the types for which IsPrimitive returns true , though, is a subjective matter since there is no absolute list... the ultimate choice is yours (you might want to include decimal as well, for example); and it should definitely be documented (at least in a comment, preferably an XML one).

Based on information in this question , you can accomplish this using the following code:

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());
    }
}

The set of public key tokens are valid for .NET 2.0 and higher (including .NET 4.0). The ByteArrayEqualityComparer class looks like:

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();
    }
}

You would then use this method like:

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

You might be able to get by, by checking the full name of the type or the assembly as below,

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

The easiest way I followed is to verify the namespace to figure out if its one of your custom types. For instance, your namespace might be "YourCompany.YourDepartment" and this can be verified against the type's Namespace.

A very simple, rudimentary way of determing whether a type is provided by the BCL/CLR is:

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

Bear in mind that using Type.IsPrimitive will return false for System.String , so it depends on what definition of "primitive" you're using as to whether it's suitable or not.

It sounds like you have a need to distinguish between types that you made yourself from everything else. Just create a custom attribute that you put on each of your types, like this:

[CustomAttribute]
struct MyDataType
{
....
}

Another option is to create an interface that all of your own custom types implement. Then it's easy to see if you need to do something special with that instance just by doing if (x is ICustom) ... .

If it's possible to put them all in the same namespace or assembly, those are also easy to check with reflection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM