2010-05-27 77 views
3

我想一個C#風格的轉換一般類型,如:轉換從C#風格的泛型類型定義字符串CLR風格

"System.Dictionary<System.String, System.String>" 

爲了它的CLR等效:

"System.Dictionary`1[System.String, System.String]" 

和背部。有沒有簡單的方法來做到這一點,還是我不得不求助於字符串操作?

編輯:

我只有在C#/ VB /等風格形式字符串表示。我手邊沒有Type對象或類似的東西。另一個問題是:如何從像"System.Dictionary<System.String, System.String>"這樣的字符串表示中獲得一個Type對象(之後我可以獲得該類型對象的全名)。

編輯#2:

理由:我創建對象的動態使用CodeDom。我生成CodeDom的輸入可能包含C#(或任何其他專有的如VB.NET)格式的類型,但我必須在僅接受CLR樣式格式的CodeTypeReference內使用它們。

+0

如果您嘗試將'C#'樣式轉換爲實際的.Net類型,您正在尋找很多痛苦。您最好的選擇是創建一個與您的CodeDOM代碼相關的查找表。它將包含'C#'類型和.Net類型名稱的列表。 – 2010-05-28 02:00:14

回答

2

我相信,我過去遇到過類似的問題,寫了下面的工具方法來解決這個問題:

// Utilitiy to convert class name string to namespace-qualified name 
    public static Type GetTypeByName(string ClassName, 
     string TypesNamespacePrefix = "AssemblyTopLevel.AssemblyMidLevel.", 
     Dictionary<string, Type> ConcreteTypeMap = null) 
    { 
     if ((ConcreteTypeMap != null) && (ConcreteTypeMap.ContainsKey(ClassName))) 
      return ConcreteTypeMap[ClassName]; 

     if ((ConcreteTypeMap != null) && (ConcreteTypeMap.ContainsKey(TypesNamespacePrefix + ClassName))) 
      return ConcreteTypeMap[TypesNamespacePrefix + ClassName]; 

     try 
     { 
      if (Type.GetType(ClassName) != null) 
       return Type.GetType(ClassName); 
     } 
     catch { } 

     try 
     { 
      if (Type.GetType(TypesNamespacePrefix + ClassName) != null) 
       return Type.GetType(TypesNamespacePrefix + ClassName); 
     } 
     catch { } 

     Stack<int> GenericCounterStack = new Stack<int>(); 
     Stack<int> GenericStartIndexStack = new Stack<int>(); 
     Dictionary<int, int> GenericCountMapByStartIndex = new Dictionary<int, int>(); 
     int Count = 1; 
     int GenericStartIndex = -1; 
     int PreviousHighestGenericIndex = -1; 

     foreach (char c in ClassName) 
     { 
      if (c.Equals('<')) 
      { 
       if (GenericStartIndex != -1) 
       { 
        GenericCounterStack.Push(Count); 
        GenericStartIndexStack.Push(GenericStartIndex); 
       } 
       Count = 1; 
       GenericStartIndex = PreviousHighestGenericIndex + 1; 
       PreviousHighestGenericIndex = Math.Max(GenericStartIndex, PreviousHighestGenericIndex); 
      } 
      else if (c.Equals(',')) 
      { 
       Count++; 
      } 
      else if (c.Equals('>')) 
      { 
       GenericCountMapByStartIndex[GenericStartIndex] = Count; 
       if (GenericCounterStack.Count != 0) 
        Count = GenericCounterStack.Pop(); 
       if (GenericStartIndexStack.Count != 0) 
        GenericStartIndex = GenericStartIndexStack.Pop(); 
      } 
     } 

     ClassName = ClassName.Replace("<" + TypesNamespacePrefix, "<"); 

     StringBuilder FullyQualifiedClassName = new StringBuilder(TypesNamespacePrefix); 

     GenericStartIndex = 0; 
     foreach (char c in ClassName) 
     { 
      if (c.Equals('<')) 
      { 
       FullyQualifiedClassName.Append("`" + GenericCountMapByStartIndex[GenericStartIndex].ToString() 
        + "[" + TypesNamespacePrefix); 
       GenericStartIndex++; 
      } 
      else if (c.Equals(',')) 
      { 
       FullyQualifiedClassName.Append("," + TypesNamespacePrefix); 
      } 
      else if (c.Equals('>')) 
      { 
       FullyQualifiedClassName.Append("]"); 
      } 
      else 
       FullyQualifiedClassName.Append(c); 
     } 

     ClassName = FullyQualifiedClassName.ToString(); 

     return Type.GetType(ClassName); 
    } 

您可任選提供具體類型圖,以針對常見情況優化:

static readonly Dictionary <string, Type> MyConcreteTypeMap = new Dictionary<string,Type>() 
    { 
     {"SomeClass", typeof(SomeClass)}, 
     {"AnotherClass", typeof(AnotherClass)} 
    } 

所以,調用看起來是這樣的:

Type DesiredType = GetTypeByName("SomeClass", "", MyConcreteTypeMap); 

Type DesiredType = GetTypeByName("SomeOtherClass", "MyAssemblyTopLevel.MyAssemblyMidLevel."); 

Type DesiredType = GetTypeByName("SomeOtherClass"); 

,或者相當有效,

Type DesiredType = GetTypeByName("SomeOtherClass<OuterTemplate<InnerTemplate1,InnerTemplate2<InnerInnerTemplate1>>>"); 

,或者對原來的例子,

Type DesiredType = GetTypeByName("Dictionary<String,String>", "System."); 
0
typeof(System.Dictionary<System.String>, System.String>).FullName 

至於相反,沒有任何線索:(

0

我不知道我完全理解你的問題。 反正 - 當您實例化一個遺傳類Class<T1, ... ,Tn>在命名空間命名空間的定義,例如

Namespace.Class<T1, ... ,Tn> a = new Namespace.Class<Type1,...,Typen>(); 

a.GetType()。全名會給你的類 的完整字符串表示,這將是"Namespace.Class'n<Type1,...,Typen>"

0

typeof(System.Dictionary<System.String, System.String>).FullName應該讓你這樣的:

System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 

可能需要做的類型參數規範內部完整的類型名稱一些替代品。不過,如果你使用下面的代碼

typeof(Dictionary<System.String, System.String>).ToString() 

你會得到這樣的事情:

System.Collections.Generic.Dictionary`2[System.String,System.String] 

要重新轉換爲Type使用

Type.GetType("System.Collections.Generic.Dictionary`2[System.String,System.String]"); 

編輯我試過黑客這與動態表達,但沒有太多的運氣。我認爲,除了解析字符串之外,您可以使用「核選項」並使用CSharpCodeProvider編譯DLL,然後使用Assembly.LoadFile加載它並執行將評估typeof(...)的方法。

+0

我只有C#風格的字符串表示形式。請參閱編輯。 – SztupY 2010-05-27 23:46:06

+0

嗯。不是人們想要正常做的事。如果你有C#代碼,你可以編譯它。如果你有一個類型的字符串表示,它通常被序列化爲字符串,然後反序列化。這兩種情況都得到了框架的支持。你能提供更多關於你在做什麼的背景嗎? – 2010-05-27 23:54:06

+0

上下文請參閱edit2。 – SztupY 2010-05-28 00:09:14

0

我認爲這就是你要找的...

var dict = new Dictionary<string, string>(); 
var type = dict.GetType(); 
var typeName = type.FullName; 
var newType = Type.GetType(typeName); 

Console.WriteLine(type == newType); //true 
+0

我只有C#風格的字符串表示形式 – SztupY 2010-05-27 23:45:33

+0

@SztupY:如果您想創建對象/類型的實例,則可以使用CodeDom而不是字符串操作。但你最好打賭可能會寫一些轉換器/解析器的字符串值。用正確的'Type.FullName'或'Type.AssemblyQualifiedName'替換'C#'樣式值是一種選擇嗎? – 2010-05-28 01:50:27

+0

CodeDOM引用鏈接... http://msdn.microsoft.com/en-us/library/f1dfsbhc.aspx – 2010-05-28 01:50:52

4

對於.NET到C#的方向,我看不到一個簡單的方法來做到這一點;你可能不得不自己分析類型。

在另一個方向上,這是很容易:

public static string DotNetToCSharp(string tyName) { 
    var provider = new Microsoft.CSharp.CSharpCodeProvider(); 
    return provider.GetTypeOutput(new System.CodeDom.CodeTypeReference(tyName)); 
} 
+0

對於其他方式,似乎我不得不求助於codesnippets(或手工解析它) – SztupY 2010-05-29 09:35:55