2009-04-06 23 views
76

私はMyClass<T>です。ジェネリック型を文字列表現から取得するにはどうすればよいですか?

そして、私はこれを持っていますstring s = "MyClass<AnotherClass>";。文字列sからTypeを取得するにはどうすればよいですか?

一つの方法(醜い)は「<」と「>」を解析することで、実行します。

Type acType = Type.GetType("AnotherClass"); 
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType); 

しかしなどあらゆる解析、なしで、最終的なタイプを取得するためのクリーンな方法は何ですか?

答えて

90

format for genericsは名前、 `文字、数ありますタイプパラメータの後に角括弧で囲まれたタイプのカンマ区切りリストが続きます。

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]"); 

ジェネリックのC#構文からCLRが望む種類の文字列に変換する簡単な方法があるかどうかはわかりません。私はあなたが質問で言及したようにそれを解析する簡単な正規表現を書いていますが、タイプパラメタとしてネストされたジェネリックスを持つ能力をあきらめないと、解析は非常に複雑になります。

+0

+1 - すばらしい答え、ありがとう!私はジェネリックスを扱う方法を見つけようとしていました。 –

+0

ありがとうございます。これはうまくいき、このように文字列をフォーマットするコードを変更する必要があります。しかし、単純に "MyClass "という文字列を使用して、Typeインスタンスを取得する方法と同じ方法が残っているのだろうかと疑問に思っていました。多くのクリーナーに見えます。 – DeeStackOverflow

+0

このように文字列を書式設定するコードを変更する必要はありません。型のToString()を呼び出すだけです。 –

38

チェックアウトActivator.CreateInstance - あなたはあなたが必要タイプのインスタンスを与えるstring

Activator.CreateInstance("myAssembly", "myType") 

このようなタイプ

Activator.CreateInstance(typeof(MyType)) 

またはアセンブリとタイプ名を持つとそれを呼び出すことができます。

あなたではなく、インスタンスよりTypeが必要な場合は、例えばType.GetType()方法と、あなたが興味を持っているタイプの完全修飾名、使用:

string s = "System.Text.StringBuilder"; 
Type myClassType = Type.GetType(s); 

質問にあなたにTypeをあげます。

+2

これは単なるコードスニペットに基づい種類、ないのSystem.Typeインスタンスのインスタンスを取得し、どのようなOPのようですを探している。 –

0

私はこれを解析するのに時間があまりありませんが、私はいくつかの同様の答えを見たと思います。特に、私は、彼らはあなたがここで何をしたいのかを正確にやっていると思う:

Entity Framework Generic Repository Error

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>(); 

うまくいけば、このことができます、これがない場合は、私はより具体的に教えてください。

3

だけで、文字列から型オブジェクトを取得するために使用:

Type mytype = Type.GetType(typeName); 

あなたはその後、Activator.CreateInstance()にこれを渡すことができます。

Activator.CreateInstance(mytype); 
26

私はこのようなものが必要でした。私は必要な単純な型名を解析するコードを書きました。もちろん、改善の余地があります。List<string>のような一般的なタイプの名前は認識されませんが、stringint[]decimal?などの場合は問題ありません。これが誰にも役立つ場合のための共有。それを使用して

public static class TypeExtensions 
{ 
    public static Type GetTypeFromSimpleName(string typeName) 
    { 
    if (typeName == null) 
     throw new ArgumentNullException("typeName"); 

    bool isArray = false, isNullable = false; 

    if (typeName.IndexOf("[]") != -1) 
    { 
     isArray = true; 
     typeName = typeName.Remove(typeName.IndexOf("[]"), 2); 
    } 

    if (typeName.IndexOf("?") != -1) 
    { 
     isNullable = true; 
     typeName = typeName.Remove(typeName.IndexOf("?"), 1); 
    } 

    typeName = typeName.ToLower(); 

    string parsedTypeName = null; 
    switch (typeName) 
    { 
     case "bool": 
     case "boolean": 
     parsedTypeName = "System.Boolean"; 
     break; 
     case "byte": 
     parsedTypeName = "System.Byte"; 
     break; 
     case "char": 
     parsedTypeName = "System.Char"; 
     break; 
     case "datetime": 
     parsedTypeName = "System.DateTime"; 
     break; 
     case "datetimeoffset": 
     parsedTypeName = "System.DateTimeOffset"; 
     break; 
     case "decimal": 
     parsedTypeName = "System.Decimal"; 
     break; 
     case "double": 
     parsedTypeName = "System.Double"; 
     break; 
     case "float": 
     parsedTypeName = "System.Single"; 
     break; 
     case "int16": 
     case "short": 
     parsedTypeName = "System.Int16"; 
     break; 
     case "int32": 
     case "int": 
     parsedTypeName = "System.Int32"; 
     break; 
     case "int64": 
     case "long": 
     parsedTypeName = "System.Int64"; 
     break; 
     case "object": 
     parsedTypeName = "System.Object"; 
     break; 
     case "sbyte": 
     parsedTypeName = "System.SByte"; 
     break; 
     case "string": 
     parsedTypeName = "System.String"; 
     break; 
     case "timespan": 
     parsedTypeName = "System.TimeSpan"; 
     break; 
     case "uint16": 
     case "ushort": 
     parsedTypeName = "System.UInt16"; 
     break; 
     case "uint32": 
     case "uint": 
     parsedTypeName = "System.UInt32"; 
     break; 
     case "uint64": 
     case "ulong": 
     parsedTypeName = "System.UInt64"; 
     break; 
    } 

    if (parsedTypeName != null) 
    { 
     if (isArray) 
     parsedTypeName = parsedTypeName + "[]"; 

     if (isNullable) 
     parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]"); 
    } 
    else 
     parsedTypeName = typeName; 

    // Expected to throw an exception in case the type has not been recognized. 
    return Type.GetType(parsedTypeName); 
    } 
} 

これを書いてと同じくらい簡単です:

Type t; 

t = TypeExtensions.GetTypeFromSimpleName("string"); 
t = TypeExtensions.GetTypeFromSimpleName("int[]"); 
t = TypeExtensions.GetTypeFromSimpleName("decimal?"); 
+5

これは驚くほど便利なコードです。 –

+1

ショート、パーフェクト、非常に便利!ありがとう – xrnd

関連する問題