Type.GetType(string) question

M

Martin Eckart

Hi folks,

Who can explain me why the following expression does not result in getting
the correct type, but null:

Type t = Type.GetType("System.Xml.XmlReader");

For "System.String" it works as well as for "System.IO.Stream" or
"System.Globalization.CultureInfo". Does that related to the constructor of
XmlReader being not public?

Thanks,
Martin
 
M

Marc Gravell

Type.GetType() doesn't automatically search all assemblies for the type;
actually, it expects an "assembly qualified name", but will forgive
you (i.e. allow the short name) if the type is found in either the
calling assembly (your code) or mscorlib.dll (common types).

The following is the aqn version of XmlReader (watch for wrap):

Type t = Type.GetType("System.Xml.XmlReader, System.Xml,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

The easiest way to get the aqn is via:
string aqn = typeof(XmlReader).AssemblyQualifiedName;

(then write that to the trace or something if you want it for a config
file etc)

Marc
 
M

Martin Eckart

Hi Marc,

That already helps.

Now, the issue I have is that I get a string value set to
"System.Xml.XmlReader". But it could also be "System.String" or
"System.Xml.XmlNodeList" or whatever. Therefore I cannot issue the code line
string aqn = typeof(XmlReader).AssemblyQualifiedName;
statically, but have to replace the "typeof(XmlReader)" by something like
"typeof(<myInputString>)".

Is there a way to accomplish that?

Thanks,
Martin
 
M

Martin Eckart

Yes, have. Has nothing do to with it.


Who can explain me why the following expression does not result in
getting
the correct type, but null:

Type t = Type.GetType("System.Xml.XmlReader");

Do you have the System.Xml assembly referenced in your assembly?

Pete
 
J

Jon Skeet [C# MVP]

That already helps.

Now, the issue I have is that I get a string value set to
"System.Xml.XmlReader". But it could also be "System.String" or
"System.Xml.XmlNodeList" or whatever. Therefore I cannot issue the code line
string aqn = typeof(XmlReader).AssemblyQualifiedName;
statically, but have to replace the "typeof(XmlReader)" by something like
"typeof(<myInputString>)".

Is there a way to accomplish that?

No - typeof(...) is a compile-time operator - it looks up the type
name based on the context of the code and the referenced assemblies,
and works out the fully-qualified name at compile-time.

What you *can* do is recursively look through the assemblies
referenced by your current assembly (I can't remember the method name
off hand, but it's something obvious like
Assembly.GetReferencedAssemblies) and call Assembly.GetType on each of
those assemblies until you find the type.

Jon
 
M

Marc Gravell

The "typeof" line was just so you could obtain the assembly-qualified
name of the type - this isn't something you'd normally keep in the real
code. The idea being to use the assembly-qualified name *instead* of
"System.Xml.XmlReader". Of course, if this isn't an option you'll have
to start trawling assemlbies...

Marc
 
M

Marc Gravell

What you *can* do is recursively look through the assemblies
referenced by your current assembly

Actually, one thing to note here is that the compiler is clever - it
will drop things that you have referenced but not used... just one to
watch if it doesn't work. You also need to watch for the circular
reference at the bottom ;-p

But something like below.

Marc

using System;
using System.Collections.Generic;
using System.Reflection;
static class Program
{
static void Main()
{
Type type = GetType("System.Xml.XmlReader");
}
static Type GetType(string name)
{
// tryu the lazy way first
Type type = Type.GetType(name);
if (type != null) return type;

List<string> skip = new List<string>();
AssemblyName root = Assembly.GetEntryAssembly().GetName();
return WalkAssemblies(name, root, skip);
}
static Type WalkAssemblies(string name, AssemblyName an,
IList<string> skip)
{
// check "an" for the type
skip.Add(an.FullName);
Assembly a;
try {
a = Assembly.Load(an);
} catch {
return null; // oops
}
Type type = a.GetType(name);
if (type != null) return type;

// see what is referenced
foreach(AssemblyName nextRef in a.GetReferencedAssemblies()) {
if(skip.Contains(nextRef.FullName)) continue;
type = WalkAssemblies(name, nextRef, skip);
if (type != null) return type;
}
return null;

}
}
 
H

Hans Kesting

Marc Gravell said:
Type.GetType() doesn't automatically search all assemblies for the type;
actually, it expects an "assembly qualified name", but will forgive you
(i.e. allow the short name) if the type is found in either the calling
assembly (your code) or mscorlib.dll (common types).

The following is the aqn version of XmlReader (watch for wrap):

Type t = Type.GetType("System.Xml.XmlReader, System.Xml, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089");

If you use just typename and assembly-name (no "Version" etc), then GetType
will find it (*if* the assembly was referenced).
So: Type t = Type.GetType("System.Xml.XmlReader, System.Xml");

Hans Kesting
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top