C# 使用字段/属性命名约定从接口自动生成类
如何使用约定从接口自动创建类的默认实现。换句话说,如果我有一个接口:C# 使用字段/属性命名约定从接口自动生成类,c#,.net,interface,naming-conventions,code-generation,C#,.net,Interface,Naming Conventions,Code Generation,如何使用约定从接口自动创建类的默认实现。换句话说,如果我有一个接口: public interface ISample { int SampleID {get; set;} string SampleName {get; set;} } 是否有代码片段、T4模板或其他方法可以从上面的接口自动生成下面的类?如您所见,我希望在字段名称前加下划线,然后使字段与属性名称相同,但首字母小写: public class Sample { private int _sample
public interface ISample
{
int SampleID {get; set;}
string SampleName {get; set;}
}
是否有代码片段、T4模板或其他方法可以从上面的接口自动生成下面的类?如您所见,我希望在字段名称前加下划线,然后使字段与属性名称相同,但首字母小写:
public class Sample
{
private int _sampleID;
public int SampleID
{
get { return _sampleID;}
set { _sampleID = value; }
}
private string _sampleName;
public string SampleName
{
get { return _sampleName;}
set { _sampleName = value; }
}
}
我不确定T4在可读性方面是否是最简单的解决方案,但您也可以使用另一种代码生成工具: 这个概念非常简单:代码由组合在一起的构建块组成 当时机成熟时,这些构建块将被解析为所选择的语言。最终得到的是一个字符串,其中包含新创建程序的源代码。之后,您可以将其写入文本文件以供进一步使用 正如您所注意到的:没有编译时结果,一切都是运行时的。如果您真的想要compiletime,那么应该使用T4 守则:
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
using System.Text;
namespace TTTTTest
{
internal class Program
{
private static void Main(string[] args)
{
new Program();
}
public Program()
{
// Create namespace
var myNs = new CodeNamespace("MyNamespace");
myNs.Imports.AddRange(new[]
{
new CodeNamespaceImport("System"),
new CodeNamespaceImport("System.Text")
});
// Create class
var myClass = new CodeTypeDeclaration("MyClass")
{
TypeAttributes = TypeAttributes.Public
};
// Add properties to class
var interfaceToUse = typeof (ISample);
foreach (var prop in interfaceToUse.GetProperties())
{
ImplementProperties(ref myClass, prop);
}
// Add class to namespace
myNs.Types.Add(myClass);
Console.WriteLine(GenerateCode(myNs));
Console.ReadKey();
}
private string GenerateCode(CodeNamespace ns)
{
var options = new CodeGeneratorOptions
{
BracingStyle = "C",
IndentString = " ",
BlankLinesBetweenMembers = false
};
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
CodeDomProvider.CreateProvider("C#").GenerateCodeFromNamespace(ns, writer, options);
}
return sb.ToString();
}
private void ImplementProperties(ref CodeTypeDeclaration myClass, PropertyInfo property)
{
// Add private backing field
var backingField = new CodeMemberField(property.PropertyType, GetBackingFieldName(property.Name))
{
Attributes = MemberAttributes.Private
};
// Add new property
var newProperty = new CodeMemberProperty
{
Attributes = MemberAttributes.Public | MemberAttributes.Final,
Type = new CodeTypeReference(property.PropertyType),
Name = property.Name
};
// Get reference to backing field
var backingRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name);
// Add statement to getter
newProperty.GetStatements.Add(new CodeMethodReturnStatement(backingRef));
// Add statement to setter
newProperty.SetStatements.Add(
new CodeAssignStatement(
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name),
new CodePropertySetValueReferenceExpression()));
// Add members to class
myClass.Members.Add(backingField);
myClass.Members.Add(newProperty);
}
private string GetBackingFieldName(string name)
{
return "_" + name.Substring(0, 1).ToLower() + name.Substring(1);
}
}
internal interface ISample
{
int SampleID { get; set; }
string SampleName { get; set; }
}
}
这将产生:
太棒了,不是吗
旁注:属性是给定的Attributes=MemberAttributes.Public | MemberAttributes.Final
,因为省略MemberAttributes.Final
会使它变成虚拟的
最后但并非最不重要的是:这种令人敬畏的灵感