Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用字段/属性命名约定从接口自动生成类_C#_.net_Interface_Naming Conventions_Code Generation - Fatal编程技术网

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
会使它变成
虚拟的

最后但并非最不重要的是:这种令人敬畏的灵感