System.Type類的名稱屬性在泛型類型的情況下返回一個奇怪的結果。有沒有一種方式來獲得類型名稱的格式與我指定的方式更接近? 例如:typeof(List<string>).OriginalName == "List<string>"
C#:「漂亮」類型名稱函數?
回答
我明白了,我必須自己寫這個。這是我的解決方案(它實際上比要求的要多一點)。它可能是有幫助的。
using System.Reflection;
using HWClassLibrary.Debug;
using System.Collections.Generic;
using System.Linq;
using System;
namespace HWClassLibrary.Helper
{
public static class TypeNameExtender
{
private static IEnumerable<Type> _referencedTypesCache;
public static void OnModuleLoaded() { _referencedTypesCache = null; }
public static string PrettyName(this Type type)
{
if(type == typeof(int))
return "int";
if(type == typeof(string))
return "string";
var result = PrettyTypeName(type);
if(type.IsGenericType)
result = result + PrettyNameForGeneric(type.GetGenericArguments());
return result;
}
private static string PrettyTypeName(Type type)
{
var result = type.Name;
if(type.IsGenericType)
result = result.Remove(result.IndexOf('`'));
if (type.IsNested && !type.IsGenericParameter)
return type.DeclaringType.PrettyName() + "." + result;
if(type.Namespace == null)
return result;
var conflictingTypes = ReferencedTypes
.Where(definedType => definedType.Name == type.Name && definedType.Namespace != type.Namespace)
.ToArray();
var namespaceParts = type.Namespace.Split('.').Reverse().ToArray();
var namespacePart = "";
for(var i = 0; i < namespaceParts.Length && conflictingTypes.Length > 0; i++)
{
namespacePart = namespaceParts[i] + "." + namespacePart;
conflictingTypes = conflictingTypes
.Where(conflictingType => (conflictingType.Namespace + ".").EndsWith(namespacePart))
.ToArray();
}
return namespacePart + result;
}
private static IEnumerable<Type> ReferencedTypes
{
get
{
if(_referencedTypesCache == null)
_referencedTypesCache = Assembly.GetEntryAssembly().GetReferencedTypes();
return _referencedTypesCache;
}
}
private static string PrettyNameForGeneric(Type[] types)
{
var result = "";
var delim = "<";
foreach(var t in types)
{
result += delim;
delim = ",";
result += t.PrettyName();
}
return result + ">";
}
}
}
你必須自己寫這個。請記住,Type.Name
等正在調用生活在CLR中的方法,並且可以從多種語言中調用。這就是爲什麼它們不像C#或VB或調用者編碼的語言那樣回來,而是看起來像CLR表示。
還要注意,string
以及什麼不是別名,如CLS類型,如System.String
。同樣,這在你看到的格式中扮演着一個角色。
使用反射並不困難,但我質疑它的價值。
我想知道爲什麼這是downvoted。 – jason
在你的榜樣,你可以期望的類型,所以你可以嘗試
public class test<T> where T : class
{
public List<String> tt
{
get;
set;
}
}
///////////////////////////
test<List<String>> tt = new test<List<String>>();
if(tt.GetType().FullName.Contains(TypeOf(List<String>).FullName))
{
//do something
}
else
{
//do something else
}
用「漂亮」的名稱問題是他們根據你所使用的語言是不同的。想象一下,如果OriginalName
返回C#語法,VB.NET開發人員會感到驚訝。
然而,這是很很容易這樣做你自己:
private static string PrettyName(Type type)
{
if (type.GetGenericArguments().Length == 0)
{
return type.Name;
}
var genericArguments = type.GetGenericArguments();
var typeDefeninition = type.Name;
var unmangledName = typeDefeninition.Substring(0, typeDefeninition.IndexOf("`"));
return unmangledName + "<" + String.Join(",", genericArguments.Select(PrettyName)) + ">";
}
這將遞歸解析非託管的名稱,因此,如果您有類似Dictionary<string, IList<string>>
它應該仍然工作。
理想情況下,這需要進一步的開發來處理'Dictionary
我以前CodeDomProvider
轉換爲C#:
public static string GetOriginalName(this Type type)
{
string TypeName = type.FullName.Replace(type.Namespace + ".", "");//Removing the namespace
var provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp"); //You can also use "VisualBasic"
var reference = new System.CodeDom.CodeTypeReference(TypeName);
return provider.GetTypeOutput(reference);
}
如果我想省略命名空間,該怎麼辦? – svick
您可以使用type.Name而不是type.FullName我想這樣您就不必自己刪除名稱空間。對不起,我現在看到你沒有那樣獲取泛型參數。 – riezebosch
我知道你要比較的類型。
要做到這一點,最好的辦法...
myVar is List<string>
或
myVar.GetType() == myOtherVar.GetType()
如果您不需要這些......請忽略我的答案。
像哈羅德·霍耶的答案,但包括nullables和幾個內置類型:
/// <summary>
/// Get full type name with full namespace names
/// </summary>
/// <param name="type">
/// The type to get the C# name for (may be a generic type or a nullable type).
/// </param>
/// <returns>
/// Full type name, fully qualified namespaces
/// </returns>
public static string CSharpName(this Type type)
{
Type nullableType = Nullable.GetUnderlyingType(type);
string nullableText;
if (nullableType != null)
{
type = nullableType;
nullableText = "?";
}
else
{
nullableText = string.Empty;
}
if (type.IsGenericType)
{
return string.Format(
"{0}<{1}>{2}",
type.Name.Substring(0, type.Name.IndexOf('`')),
string.Join(", ", type.GetGenericArguments().Select(ga => ga.CSharpName())),
nullableText);
}
switch (type.Name)
{
case "String":
return "string";
case "Int32":
return "int" + nullableText;
case "Decimal":
return "decimal" + nullableText;
case "Object":
return "object" + nullableText;
case "Void":
return "void" + nullableText;
default:
return (string.IsNullOrWhiteSpace(type.FullName) ? type.Name : type.FullName) + nullableText;
}
}
第一:榮譽對納維德車輪再造迴避。如果可以的話,我會加倍努力。
這裏有幾點需要補充,如果有人走這條路(至少對於VS10/.Net 4):
*嘗試使用TypeType參數的CodeTypeReference變體之一。這樣可以避免使用字符串類型名稱(如尾隨&)的一些缺陷,並且意味着您可以取回bool
而不是System.Boolean
等等。您可以獲取像這樣的很多類型的完整名稱空間,但是您總是可以擺脫稍後名稱空間部分。
*簡單Nullables往往回來的形式System.Nullable<int>
而非int?
- 您可以轉換成更好的語法與答案正則表達式,如: const string NullablePattern = @"System.Nullable<(?<nulledType>[\w\.]+)>"; const string NullableReplacement = @"${nulledType}?"; answer = Regex.Replace(answer, NullablePattern, NullableReplacement);
*方法的參數像out T?
的類型給出了一個非常不透明的字符串。如果有人有處理這種事情的優雅方式,我很想知道這件事。
希望這一切都變得非常容易與羅斯林。
對不起,Nullable模式是混亂的。應該是@"System\.Nullable<(?
–
這是我的實現。它是爲描述方法而創建的,因此它處理ref
和out
關鍵字。
private static Dictionary<Type, string> shorthandMap = new Dictionary<Type, string>
{
{ typeof(Boolean), "bool" },
{ typeof(Byte), "byte" },
{ typeof(Char), "char" },
{ typeof(Decimal), "decimal" },
{ typeof(Double), "double" },
{ typeof(Single), "float" },
{ typeof(Int32), "int" },
{ typeof(Int64), "long" },
{ typeof(SByte), "sbyte" },
{ typeof(Int16), "short" },
{ typeof(String), "string" },
{ typeof(UInt32), "uint" },
{ typeof(UInt64), "ulong" },
{ typeof(UInt16), "ushort" },
};
private static string CSharpTypeName(Type type, bool isOut = false)
{
if (type.IsByRef)
{
return String.Format("{0} {1}", isOut ? "out" : "ref", CSharpTypeName(type.GetElementType()));
}
if (type.IsGenericType)
{
if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return String.Format("{0}?", CSharpTypeName(Nullable.GetUnderlyingType(type)));
}
else
{
return String.Format("{0}<{1}>", type.Name.Split('`')[0],
String.Join(", ", type.GenericTypeArguments.Select(a => CSharpTypeName(a)).ToArray()));
}
}
if (type.IsArray)
{
return String.Format("{0}[]", CSharpTypeName(type.GetElementType()));
}
return shorthandMap.ContainsKey(type) ? shorthandMap[type] : type.Name;
}
調用代碼看起來是這樣的:
string line = String.Format("{0}.{1}({2})",
method.DeclaringType.Name,
method.Name,
String.Join(", ", method.GetParameters().Select(p => CSharpTypeName(p.ParameterType, p.IsOut) + " " + p.Name).ToArray()));
凡method
是MethodInfo
實例。
注意:我沒有必要描述任何多維數組類型,所以我沒有打算實現這個描述,但通過調用type.GetArrayRank()
來添加它會相當容易。
利用CodeDomProvider
的最小工作解決方案是首先控制CodeTypeReference
實例的構建方式。有特殊情況僅適用於泛型類型和多等級的陣列,所以我們只需要關心那些:
static CodeTypeReference CreateTypeReference(Type type)
{
var typeName = (type.IsPrimitive || type == typeof(string)) ? type.FullName : type.Name;
var reference = new CodeTypeReference(typeName);
if (type.IsArray)
{
reference.ArrayElementType = CreateTypeReference(type.GetElementType());
reference.ArrayRank = type.GetArrayRank();
}
if (type.IsGenericType)
{
foreach (var argument in type.GetGenericArguments())
{
reference.TypeArguments.Add(CreateTypeReference(argument));
}
}
return reference;
}
使用該改造的工廠方法,則有可能使用適當的代碼提供者得到相當打字,如下所示:
using (var provider = new CSharpCodeProvider())
{
var reference = CreateTypeReference(typeof(IObservable<IEnumerable<Tuple<int?, string>>>[,]));
var output = provider.GetTypeOutput(reference);
Console.WriteLine(output);
}
上述代碼返回IObservable<IEnumerable<Tuple<Nullable<int>, string>>>[,]
。唯一沒有得到妥善處理的特殊情況是Nullable
類型,但這實際上比CodeDomProvider
更重要。
- 1. 在C#(窗體)漂亮的鍵名稱
- 2. 更漂亮的TypeScript匿名類聲明?
- 3. C++函數參數數據類型沒有名稱
- 4. typedef函數不是類型名稱嗎?
- 5. c + +返回類型和類型名稱
- 6. Objective-C - Unknwn類型名稱
- 7. 未知類型名稱C
- 8. C#類型的名稱,而不是CLR類型名稱
- 9. C未知類型名稱'數據'
- 10. 獲取類名稱函數的名稱
- 11. 更漂亮,縮進,漂亮的印刷
- 12. 無效名稱(類型名稱1,類型名稱2,類型名稱3 [名稱1] [名稱2]);
- 13. 語法類型函數中的名稱(類型)
- 14. C#同名類型名稱約定
- 15. 的.htaccess漂亮的URL稱號網址
- 16. C#獲取泛型類型名稱
- 17. 與整數類型名稱匹配的浮點類型名稱?
- 18. MVC5在@ Html.ActionLink中顯示漂亮的顯示名稱
- 19. C函數指針爲參數`類型名稱'指定錯誤存儲類
- 20. *是C++函數名稱?
- 21. C中的函數名稱
- 22. Unmangling C++ DLL函數名稱
- 23. C中的漂亮表格C
- 24. C函數名稱或函數指針?
- 25. C++函數類型
- 26. C++函數類型?
- 27. 漂亮打印
- 28. 「漂亮」爲Python
- 29. 漂亮的URL與參數
- 30. 漂亮的印刷數學
這很容易將自己寫成使用遞歸的擴展方法。 –
這樣的函數不在框架中,因爲它取決於您使用的語言:VB具有不同的泛型表示,我也確定其他語言。 – svick