Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine if System.Type is a custom type or a Framework type?

I want to distinctly determine if the type that I have is of custom class type (MyClass) or one provided by the Framework (System.String).

Is there any way in reflection that I can distinguish my class type from system.string or other Framework provided types?

like image 373
Nilotpal Das Avatar asked Jul 04 '10 14:07

Nilotpal Das


3 Answers

The only way to safely check if a type is part of an assembly is to check the assembly's fully qualified name which contains its name, version, culture and public key (if signed). All .Net base class libraries (BCL) are signed by microsoft using their private keys. This makes it almost impossible for anyone else to create an assembly with same fully qualified name as a base class library.

//add more .Net BCL names as necessary
var systemNames = new HashSet<string>
{
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
};

var isSystemType = systemNames.Contains(objToTest.GetType().Assembly.FullName); 

A slightly less brittle solution is to use the AssemblyName class and skip the version number/culture check. This of course assumes the public key doesn't change between versions.

//add more .Net BCL names as necessary
var systemNames = new List<AssemblyName>
{
new AssemblyName ("mscorlib, Version=4.0.0.0, Culture=neutral, " +
                  "PublicKeyToken=b77a5c561934e089"),
new AssemblyName ("System.Core, Version=4.0.0.0, Culture=neutral, "+
                  "PublicKeyToken=b77a5c561934e089")
};

var obj = GetObjectToTest();

var objAN = new AssemblyName(obj.GetType().Assembly.FullName);

bool isSystemType = systemNames.Any(
        n =>  n.Name == objAN.Name 
           && n.GetPublicKeyToken().SequenceEqual(objAN.GetPublicKeyToken()));

Most of the BCL have been signed with the same key but not all. You could use the AssemblyName class to just check the public key token. It depends on your needs.

like image 118
Bear Monkey Avatar answered Nov 03 '22 07:11

Bear Monkey


If you simply want to distinguish between MyClass and string then you can check for those types directly:

Type typeToTest = GetTypeFromSomewhere();

if (typeToTest == typeof(MyClass))
    MyClassAction();
else if (typeToTest == typeof(string))
    StringAction();
else
    NotMyClassOrString();

If you need a more general check for whether or not a given type is a framework type then you could check whether it belongs to the System namespace:

// create an array of the various public key tokens used by system assemblies
byte[][] systemTokens =
    {
        typeof(System.Object)
            .Assembly.GetName().GetPublicKeyToken(),  // B7 7A 5C 56 19 34 E0 89
        typeof(System.Web.HttpRequest)
            .Assembly.GetName().GetPublicKeyToken(),  // B0 3F 5F 7F 11 D5 0A 3A 
        typeof(System.Workflow.Runtime.WorkflowStatus)
            .Assembly.GetName().GetPublicKeyToken()   // 31 BF 38 56 AD 36 4E 35 
    };

Type typeToTest = GetTypeFromSomewhere();

string ns = typeToTest.Namespace;
byte[] token = typeToTest.Assembly.GetName().GetPublicKeyToken();

bool isSystemType = ((ns == "System") || ns.StartsWith("System."))
                    && systemTokens.Any(t => t.SequenceEqual(token));
like image 23
LukeH Avatar answered Nov 03 '22 07:11

LukeH


You can check the Assembly in which the type is declared.

object.GetType().Assembly
like image 4
Itay Karo Avatar answered Nov 03 '22 06:11

Itay Karo