如何使用短类型名称而不是完整类型名称生成代码?
How to generate code with short type names instead of full type names?
假设我想创建一个代码文件,其中包含一个字段class =37=] 其中有一些非原始非别名 类型 。让它成为众所周知的东西:StreamWriter
类型。
我添加 System.IO
导入以允许短类型引用。我以这种方式创建类型引用:
var type = new CodeTypeReference(typeof(StreamWriter));
但仍然会生成冗余类型前缀:
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 2.0.50727.1433
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Bar {
using System.IO;
public class Foo {
private System.IO.StreamWriter baz;
}
}
我知道我可以使用 string
解决问题:
var type = new CodeTypeReference("StreamWriter");
// or even
var type = new CodeTypeReference(typeof(StreamWriter).Name);
但应该有一些不错的 CodeDom 构建方式,不是吗?
P.S.: 第二种解决方法可能看起来足够类型安全,但我不知道具体类型,只知道它是从已知基类型派生的。所以,实际上它看起来像这样:
var type = new CodeTypeReference(controlData.Control.GetType().Name);
如果控件有一些“奇怪的”类型,如泛型或嵌套类型,它将生成有效代码。
如果你看看如何 CodeTypeReference
construction from Type is implemented,你会发现你可以实施类似这样的解决方法:
public static CodeTypeReference CreateShortCodeTypeReference(Type type, CodeNamespaceImportCollection imports)
{
var result = new CodeTypeReference(type);
Shortify(result, type, imports);
return result;
}
private static void Shortify(CodeTypeReference typeReference, Type type, CodeNamespaceImportCollection imports)
{
if (typeReference.ArrayRank > 0)
{
Shortify(typeReference.ArrayElementType, type, imports);
return;
}
if (type.Namespace != null && imports.Cast<CodeNamespaceImport>()
.Any(cni => cni.Namespace == type.Namespace))
{
var prefix = type.Namespace + '.';
if (prefix != null)
{
var pos = typeReference.BaseType.IndexOf(prefix);
if (pos == 0)
{
typeReference.BaseType = typeReference.BaseType.Substring(prefix.Length);
}
}
}
}
用法:
var type = CreateShortCodeTypeReference(foo.GetType(), codeNamespace.Imports);
结果:
假设 using UnityEngine.UI;
存在:
- UnityEngine.UI.Button → 按钮
- UnityEngine.UI.Button[] → 按钮[]
- UnityEngine.UI.Button[][][] → 按钮[][][]
限制:
- 不会影响泛型类型参数,例如
List<System.IO.Path>
。
- 仅对使用支持导入的 CLR 语言(如 C# 和 VB)生成代码有效。
假设我想创建一个代码文件,其中包含一个字段class =37=] 其中有一些非原始非别名 类型 。让它成为众所周知的东西:StreamWriter
类型。
我添加 System.IO
导入以允许短类型引用。我以这种方式创建类型引用:
var type = new CodeTypeReference(typeof(StreamWriter));
但仍然会生成冗余类型前缀:
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 2.0.50727.1433
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Bar {
using System.IO;
public class Foo {
private System.IO.StreamWriter baz;
}
}
我知道我可以使用 string
解决问题:
var type = new CodeTypeReference("StreamWriter");
// or even
var type = new CodeTypeReference(typeof(StreamWriter).Name);
但应该有一些不错的 CodeDom 构建方式,不是吗?
P.S.: 第二种解决方法可能看起来足够类型安全,但我不知道具体类型,只知道它是从已知基类型派生的。所以,实际上它看起来像这样:
var type = new CodeTypeReference(controlData.Control.GetType().Name);
如果控件有一些“奇怪的”类型,如泛型或嵌套类型,它将生成有效代码。
如果你看看如何 CodeTypeReference
construction from Type is implemented,你会发现你可以实施类似这样的解决方法:
public static CodeTypeReference CreateShortCodeTypeReference(Type type, CodeNamespaceImportCollection imports)
{
var result = new CodeTypeReference(type);
Shortify(result, type, imports);
return result;
}
private static void Shortify(CodeTypeReference typeReference, Type type, CodeNamespaceImportCollection imports)
{
if (typeReference.ArrayRank > 0)
{
Shortify(typeReference.ArrayElementType, type, imports);
return;
}
if (type.Namespace != null && imports.Cast<CodeNamespaceImport>()
.Any(cni => cni.Namespace == type.Namespace))
{
var prefix = type.Namespace + '.';
if (prefix != null)
{
var pos = typeReference.BaseType.IndexOf(prefix);
if (pos == 0)
{
typeReference.BaseType = typeReference.BaseType.Substring(prefix.Length);
}
}
}
}
用法:
var type = CreateShortCodeTypeReference(foo.GetType(), codeNamespace.Imports);
结果:
假设 using UnityEngine.UI;
存在:
- UnityEngine.UI.Button → 按钮
- UnityEngine.UI.Button[] → 按钮[]
- UnityEngine.UI.Button[][][] → 按钮[][][]
限制:
- 不会影响泛型类型参数,例如
List<System.IO.Path>
。 - 仅对使用支持导入的 CLR 语言(如 C# 和 VB)生成代码有效。