2013-08-06 10 views
7

Visual Studio CodeModelを使用していて、CodeTypeの汎用パラメータを取得するにはいくつかの問題があります。 FullName自分自身を解析せずにそれらを取得するには?CodeType get generic parameters

System.Func<Outer.Inner>

が定義されません:あなたは、どうかを知ることができない

それは、他の方法がないことをHow can I get the generic constraints from CodeInterface as a CodeType object?で(答えをマークされていないが)示唆されているが、これは、本当に信じられないです解析された汎用パラメータ(Outer.Inner)は、クラスInnerを含む名前空間Outerを参照しています。または、内部クラスInnerを持つクラスOuterを参照している場合は(この場合はOuter+Innerではありません)。

少なくともFullNameプロパティに、+という記号のネストされたクラスを表示する方法を知っている人は、これも素晴らしいでしょう。

答えて

0

私はanswer hereがかなり確定していると思います。これはDTEまたはDTE2ではサポートされておらず、将来サポートされる可能性は低いです。

現在のところ、Roslynを使用する唯一の方法は、プレリリースソフトウェアを使用したくないユーザーにとっては受け入れられない方法です。私はまた、(私のコンポーネントのユーザーはRoslynをインストールする必要がありますか?)必要な依存関係の種類を調べていません。

正規表現を使用して、FullName文字列から型を取得できます。しかし、具体的なタイプ(System.String)のマッピングにトークン(T)が必要な現実の私たちにとって、これはオプションではありません。

0

一般的なタイプのためにそれを行う方法はありませんが、特定のタイプに対して行う必要がある場合は、場合によっては可能です。あなたが見ることができるように

private static bool IsCollectionType(CodeType type, out CodeType elementType) 
    { 
     // string implements IEnumerable<char>, but we don't want to treat it as a collection 
     if (type.FullName == "System.String") 
     { 
      elementType = null; 
      return false; 
     } 

     var enumerable = type.Bases.OfType<CodeInterface>().FirstOrDefault(i => i.FullName.StartsWith("System.Collections.Generic.IEnumerable<")); 
     var method = enumerable?.Members.OfType<CodeFunction>().FirstOrDefault(m => m.Name == "GetEnumerator"); 
     var enumerator = method?.Type.CodeType; 
     var current = enumerator?.Members.OfType<CodeProperty>().FirstOrDefault(m => m.Name == "Current"); 
     if (current != null) 
     { 
      elementType = current.Type.CodeType; 
      return true; 
     } 

     elementType = null; 
     return false; 
    } 

、私は直接見ていないよ:

例えば、私はタイプがコレクションであり、それがある場合は、要素の型を取得するかどうかを確認するために、次のコードを持っていますジェネリック型の引数ですが、代わりにIEnumerable<T>.GetEnumerator().Currentの型を調べます。もちろん、これには作業するタイプに関する特定の知識が必要です。