web-dev-qa-db-ja.com

タイプの部分的な名前からSystem.Typeを取得する

stringの型名のみを指定してSystem.Typeを取得したい。

たとえば、オブジェクトがある場合:

MyClass abc = new MyClass();

私はそれから言うことができます:

System.Type type = abc.GetType();

しかし、もし私がすべて持っているとすれば:

string className = "MyClass";
37
Mark T

クラスがどのアセンブリであるかによって異なります。 mscorlibにある場合、またはAssemblyを呼び出す場合、必要なのは

Type type = Type.GetType("namespace.class");

ただし、他のアセンブリから参照されている場合は、次のようにする必要があります。

Assembly assembly = typeof(SomeKnownTypeInAssembly).Assembly;
Type type = Assembly.GetType("namespace.class");

//or

Type type = Type.GetType("namespace.class, Assembly");

クラス名が "MyClass"しかない場合は、名前空間名(または、参照されているアセンブリの場合は名前空間名とアセンブリ名の両方)を取得して、クラス名と連結する必要があります。何かのようなもの:

//if class is in same Assembly
var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
Type type = Type.GetType(namespace + "." + "MyClass");


//or for cases of referenced classes
var Assembly = typeof(SomeKnownTypeInAssembly).Assembly;
var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
Type type = Assembly.GetType(namespace + "." + "MyClass");
//or
Type type = Type.GetType(namespace + "." + "MyClass" + ", " + Assembly.GetName().Name);

絶対に何もない場合(アセンブリ名や名前空間名さえも知らない)、クラス名だけの場合は、アセンブリ全体をクエリして、一致する文字列を選択できます。 しかし、それはかなり遅くなるはずです

Type type = AppDomain.CurrentDomain.GetAssemblies()
                                   .SelectMany(x => x.GetTypes())
                                   .FirstOrDefault(x => x.Name == "MyClass");

これは最初に一致するクラスを返すため、アセンブリ/名前空間全体で同じ名前のクラスが複数ある場合は、それほど正確である必要はありません。いずれの場合もここでは値をキャッシュするのが理にかなっています。 少し速い方法は、1つのデフォルト名前空間があると仮定することです

Type type = AppDomain.CurrentDomain.GetAssemblies()
                                   .Select(a => new { a, a.GetTypes().First().Namespace })
                                   .Select(x => x.a.GetType(x.Namespace + "." + "MyClass"))
                                   .FirstOrDefault(x => x != null);

しかし、これも、型がアセンブリ内の他のランダムクラスと同じ名前空間を持つことを前提としています。もろい、あまり良くない。


他のドメインのクラスが必要な場合は、 このリンクに従ってすべてのアプリケーションドメインのリストを取得できます。 次に、各ドメインに対して上記と同じクエリを実行できます。タイプが存在するアセンブリがまだロードされていない場合は、Assembly.LoadAssembly.LoadFromなどを使用して手動でロードする必要があります。

39
nawfal
Type type = Type.GetType("foo.bar.MyClass, foo.bar");

[〜#〜] msdn [〜#〜] 。名前が Assembly Qualified であることを確認してください。

33

タイプを取得した後でクラスのインスタンスを作成し、メソッドを呼び出すには-

Type type = Type.GetType("foo.bar.MyClass, foo.bar");
object instanceObject = System.Reflection.Activator.CreateInstance(type);
type.InvokeMember(method, BindingFlags.InvokeMethod, null, instanceObject, new object[0]);
2
Seibar
Type type = Type.GetType("MyClass");

必ず名前空間を含めてください。大文字と小文字の区別と、型名が見つからない場合に例外がスローされるかどうかを制御するメソッドのオーバーロードがあります。

1
jalbert

現在または別のアセンブリから型を取得する別の方法。

(クラス名前空間にそのアセンブリが含まれていると想定):


public static Type GetType(string fullName) { if (string.IsNullOrEmpty(fullName)) return null; Type type = Type.GetType(fullName); if (type == null) { string targetAssembly = fullName; while (type == null && targetAssembly.Length > 0) { try { int dotInd = targetAssembly.LastIndexOf('.'); targetAssembly = dotInd >= 0 ? targetAssembly.Substring(0, dotInd) : ""; if (targetAssembly.Length > 0) type = Type.GetType(fullName + ", " + targetAssembly); } catch { } } } return type; }
1
Zbigniew Wiadro

名前とパラメーターから新しいオブジェクトを作成して初期化する簡単な方法を次に示します。

    //  Creates and initializes a new object from its name and parameters
    public Object CreateObjectByName(string name, params Object[] args)
    {
        string s = "<prefix>" + name;    // case sensitive; Type.FullName
        Type type = Type.GetType(s);
        Object o = System.Activator.CreateInstance(type, args);
        return o;
    }

これを使用する方法の1つの例は、クラス名(または部分的なクラス名)とパラメーターを含むファイルを読み取り、作成されたオブジェクトに共通の基本タイプのオブジェクトのリストに返されたオブジェクトを追加することです。

クラス名[または]がどのように見えるかを確認するには、一時的に次のようなものを使用します(クラスの名前がNewClassの場合):

    string z = (new NewClass(args)).GetType().FullName;
0
shadow

typeof演算子を使用できない場合、Type.GetType(...) mightが失敗することがあります。

代わりに、現在のドメインのアセンブリを反映させることができます。

this thread で私の応答を確認してください

0
dmihailescu