views:

114

answers:

4

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?

+3  A: 

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

object.GetType().Assembly
Itay
So the question then is: how to know that an assembly is part of the .NET framework?
Hans Passant
+3  A: 

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));
LukeH
Not really bulletproof, forinstance if the namespace is called "SystemUtil" ;)
thomask
@thomas: I realised that soon after posting but was called away before I could edit. Now fixed.
LukeH
@LukeH: I'm pretty sure you can actually write your own assembly and make the namespace `System.[something]`... I'm not a big fan of doing this, but I know some open-source projects do -- e.g., [`System.Data.SQLite`](http://sqlite.phxsoftware.com/), [`System.Drawing.Html`](http://htmlrenderer.codeplex.com/).
Dan Tao
@Dan: That's very true, although it's also a pretty bad practice. I've edited to include a check against the assembly's `PublicKeyToken` to ensure that it's a true system type. Of course, if you only want to check that it's a *core* system type then you could just do `if (typeToTest.Assembly == typeof(int).Assembly)`, but that would exclude members of the wider `System.*` namespace (for example, `XmlDocument`). I guess it really depends on what exactly the OP is trying to achieve.
LukeH
A: 

Not all framework classes start in the System namespace (they can also be Microsoft etc).

As such, you could probably compare the location of a known framework class with that of the type that you are testing such as:

  if (String.CompareOrdinal(
        Path.GetDirectoryName(typeof(String).Assembly.Location), 
        Path.GetDirectoryName(typeof(MyType).Assembly.Location)
      ) == 0)
  {
    //Framework Type
  }
  else
  {
    //3rd Party DLL
  }

Not the greatest solution; but safer than just testing if the namespace starts with System (I could create a namespace that starts with System that isn't a framework class).

Edit

Also, in addition to the above test, it wouldn't hurt to verify that the type is loaded from the Global Assembly Cache:

typeof(MyType).Assembly.GlobalAssemblyCache
Calgary Coder
@Calgary: As far as I'm aware, the BCL consists only of the `System.*` namespaces. The `Microsoft.*` namespaces are a superset of the BCL -- sometimes known as the FCL -- and aren't part of the ECMA CLI standard. http://en.wikipedia.org/wiki/Base_Class_Library
LukeH
@LukeH: Really good point. The important point I was going for was to not rely on the namespace starting with System. And as other solutions have shown, being explict is always the best bet; this is a "poor man's" check that I thought I would throw up just in case.
Calgary Coder
+4  A: 
Bear Monkey