In the previous article , Lao Zhou has the cheek to introduce the type of statement , A type is naturally a type member , so , Follow this line , Today we'll see how to add members to a type .

We all know , Common type members , For example, fields 、 attribute 、 Method 、 event . Represents the type of code member and CodeTypeDeclaration Classes have a common base class —— CodeTypeMember. After all, the type is good , Type members, too , They all have the same characteristics .

below , Let's have a brief understanding of the related types , There is a spectrum in my heart .

CodeMemberField: Field

CodeMemberProperty: attribute

CodeMemberMethod: Method

CodeConstructor: Constructors

CodeMemberEvent: event

Here's an example , Make a statement Dog class , And add one with a single string Constructor for type parameters , And one called Age Properties of .

* From the outgoing , Create layer by layer
// Compilation unit
CodeCompileUnit unit = new CodeCompileUnit();
// Namespace
CodeNamespace ns = new CodeNamespace("Sample");
// The introduction of a System Namespace
ns.Imports.Add(new CodeNamespaceImport(nameof(System)));
unit.Namespaces.Add(ns); // Declaration type
CodeTypeDeclaration t1 = new CodeTypeDeclaration("Dog");
// Prepare the arguments for the constructor
CodeParameterDeclarationExpression p = new CodeParameterDeclarationExpression(typeof(string), "dogName");
// Constructors
CodeConstructor ctr = new CodeConstructor();
t1.Members.Add(ctr); // attribute
CodeMemberProperty prty = new CodeMemberProperty();
prty.Name = "Age";
// The type of property value
prty.Type = new CodeTypeReference(typeof(int));
// Public attribute
prty.Attributes = MemberAttributes.Public;
prty.HasGet = true; // Can be read
prty.HasSet = true; // Can write

In the use of CodeMemberProperty When defining properties ,HasGet and HasSet Property is used to specify whether the property is readable or writable .

The code generated by the above example is as follows :

Here, the generated attribute is with virtual keyword , Virtual member , Classes can be derived in the future override Of . About how to get rid of this virtual keyword , You can turn it into Finnal member .  About this Attributes attribute , Lao Zhou apologized to everyone .

because MemberAttributes Enumeration is not attached Flags Description of characteristics , Lao Zhou thought it could not be used in combination , however , Later, Lao Zhou went through the experiment , It turns out that this bastard can do bit operations . Lao Zhou plans to write another article about this later .

such as , above Age attribute , If you want to get rid of it virtual keyword , It can be written like this :

prty.Attributes = MemberAttributes.Public | MemberAttributes.Final;

Another example , Declare a Demo Class , There's a private field in it ma, Pass data to... Through parameters in the public constructor ma Field .

 CodeCompileUnit unit = new CodeCompileUnit();
CodeNamespace ns = new CodeNamespace("Data");
ns.Imports.Add(new CodeNamespaceImport(nameof(System))); // Declaration type
CodeTypeDeclaration type1 = new CodeTypeDeclaration("Demo");
ns.Types.Add(type1); // Field
CodeMemberField fd = new CodeMemberField(typeof(string), "ma");
fd.Attributes = MemberAttributes.Private; // private
type1.Members.Add(fd); // Constructors
// Parameters
CodeParameterDeclarationExpression pc = new CodeParameterDeclarationExpression(typeof(string), "a");
CodeConstructor ctor = new CodeConstructor();
// public
ctor.Attributes = MemberAttributes.Public;
// Assignment statement
CodeAssignStatement ass = new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fd.Name), new CodeVariableReferenceExpression(pc.Name));
// Add an assignment statement to the method body

use CodeMemberField Declaration fields are easy to do , Just specify the field type and name . The constructor is a special method ,CodeConstructor Also inherited one Statements aggregate , Represents a statement in a method body . In the example above , Just one assignment statement in the constructor is enough .

Generated C# The code is shown in the following figure .


Let's look at the method generation , Let's start with a simple example , Generate a program called PlayMusic, No parameter , The return value type is void Methods .

 CodeMemberMethod m = new CodeMemberMethod();
m.Name = "PlayMusic";
CodeDomProvider prvd = CodeDomProvider.CreateProvider("cs");
prvd.GenerateCodeFromMember(m, Console.Out, null);

The result is shown in the figure below .

More complicated , Let's generate a class , Define a class with two parameters , And back to not void Method of type .

 CodeTypeDeclaration tp = new CodeTypeDeclaration("Calculator");
tp.Attributes = MemberAttributes.Public; CodeMemberMethod m = new CodeMemberMethod();
// Method name
m.Name = "Add";
// Public methods
m.Attributes = MemberAttributes.Public | MemberAttributes.Final;
// Return value
m.ReturnType = new CodeTypeReference(typeof(int));
// Two parameters
CodeParameterDeclarationExpression p1 = new CodeParameterDeclarationExpression(typeof(int), "m");
CodeParameterDeclarationExpression p2 = new CodeParameterDeclarationExpression(typeof(int), "n");
* Generate statements in methods return m + n
// Operation expression m+n
CodeBinaryOperatorExpression addexp = new CodeBinaryOperatorExpression();
addexp.Operator = CodeBinaryOperatorType.Add;
addexp.Left = new CodeVariableReferenceExpression(p1.Name);
addexp.Right = new CodeVariableReferenceExpression(p2.Name);
// return sentence
CodeMethodReturnStatement retstm = new CodeMethodReturnStatement(addexp);
m.Statements.Add(retstm); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");
CodeGeneratorOptions opt = new CodeGeneratorOptions
BracingStyle = "C"
provider.GenerateCodeFromType(tp, Console.Out, opt);

ReturnType Used to set the return value type of the method , Method parameters use CodeParameterDeclarationExpression To define , Attribute to expression . In the code block of the method , If you want to return , Then use return sentence ,CodeMethodReturnStatement Class represents return sentence . When using, you should specify an expression to calculate the return value , If you do not provide an expression , Go straight back ( Jump out of ), Okay, like this :


The result is code like this :

Method members , There is a special way , It's the entry point , namely Main Method , Declare entry point method , You can use specialized classes —— CodeEntryPointMethod. There is no need to specify a name when initializing , Because its name is fixed . The return value type of the entry point is usually void perhaps int, A parameter is usually an array of strings , Represents the command line parameter passed in , Of course, it can also be nonparametric .

The following code defines a Program class , Then add an entry point method to the class , Invoking in entrance point method Console.WriteLine Output string .

 CodeTypeDeclaration t = new CodeTypeDeclaration("Program");
// Entry point method 
CodeEntryPointMethod main = new CodeEntryPointMethod();
// Call a method
CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Console)), nameof(Console.WriteLine));
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(mref, new CodePrimitiveExpression("hello pig"));
main.Statements.Add(new CodeExpressionStatement(invoke));

The generated code is shown in the figure below .

If you want to compile the generated code into .exe Words , Entry points are required , Otherwise “ ha-ha ” Of .


good , drank 3 Cup of rice flowers , Now let's go on , Now it's time to generate event members .

The following code generates a separate Click event .

 CodeMemberEvent ev = new CodeMemberEvent();
ev.Attributes = MemberAttributes.Public;
ev.Name = "Click";
ev.Type = new CodeTypeReference(typeof(System.EventHandler)); CodeDomProvider p = CodeDomProvider.CreateProvider("cs");
p.GenerateCodeFromMember(ev, Console.Out, null);

Be careful , The type of event is delegate , therefore ,Type Property must be a delegate type , Although you can scribble in the code generation phase , however , If the type of the event is not delegate , At compile time , The compiler will look on your face . therefore , Let's not be too headstrong , Whatever type should be specified .

The generated events are as follows :

You must know , stay .net There is an event delegate in the class library called EventHandler<TEventArgs>, The advantage of this delegate is that we don't have to declare delegates for various custom events , Generally speaking ,TEventArgs It means EventArgs Class or its subclass .

Let's use this event delegate with generic parameters to generate event definition code .

On the first code , Let's talk about it after you've read the code .

 CodeNamespace ns = new CodeNamespace("TestSomething");
ns.Imports.Add(new CodeNamespaceImport(nameof(System))); // Custom event parameter class
CodeTypeDeclaration custEvarg = new CodeTypeDeclaration("SubmitEventArgs");
// Base class
custEvarg.BaseTypes.Add(new CodeTypeReference(typeof(EventArgs)));
// Field
CodeMemberField dtf = new CodeMemberField(typeof(byte), "m_data");
dtf.Attributes = MemberAttributes.Private;
// attribute
CodeMemberProperty dtpry = new CodeMemberProperty();
dtpry.Name = "Data";
dtpry.Attributes = MemberAttributes.Public | MemberAttributes.Final;
dtpry.Type = new CodeTypeReference(typeof(byte));
// read-only
dtpry.HasGet = true;
dtpry.HasSet = false;
// Return property value
CodeMethodReturnStatement ret = new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dtf.Name));
// Constructors
CodeConstructor ctor = new CodeConstructor();
ctor.Attributes = MemberAttributes.Public;
ctor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(byte), "data"));
ctor.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dtf.Name), new CodeVariableReferenceExpression("data"))); /**************************************************************/
CodeTypeDeclaration testtype = new CodeTypeDeclaration("Test");
// event
CodeMemberEvent eve = new CodeMemberEvent();
eve.Name = "OnSubmit";
eve.Attributes = MemberAttributes.Public;
eve.Type = new CodeTypeReference($"EventHandler`1[{custEvarg.Name}]"); CodeDomProvider p = CodeDomProvider.CreateProvider("cs");
p.GenerateCodeFromNamespace(ns, Console.Out, null);

The code is quite long , But I believe you can understand some of them .

First , A statement from EventArgs Class derived class , It's called SubmitEventArgs.

 CodeTypeDeclaration custEvarg = new CodeTypeDeclaration("SubmitEventArgs");
custEvarg.BaseTypes.Add(new CodeTypeReference(typeof(EventArgs)));

Then a private field is added , be known as m_data, The type is byte, Can pass Data return . The value of this field can be set by passing the value of the constructor parameter .

The second class is Test class , It has a public event OnSubmit, That's the point of the code , I'll copy it again .

 CodeMemberEvent eve = new CodeMemberEvent();
eve.Name = "OnSubmit";
eve.Attributes = MemberAttributes.Public;
eve.Type = new CodeTypeReference($"EventHandler`1[{custEvarg.Name}]");

What's more difficult here is the delegate type of the event , Because we use EventHandler<TEventArgs>, It has a generic parameter , And the generic parameter type is what we want to generate earlier SubmitEventArgs class . that , How to enter the full name of a type with a generic parameter , It's in this format :

< Type name >`< Number of generic parameters >[< Type list >,……n]

As in the above code ,EventHandler Like 1 Generic parameters , So the numbers are 1, namely EventHandler`1, The generic type follows , Wrap it in brackets , Representation is an array .

such as , The name of a certain class is Order, It has 2 Generic parameters , that Order<byte, int> The way to write is :

Order`[System.Byte, System.Int32]

If the type is going to write the assembly 、 Version number and so on , Just a layer of brackets , Enclose the types . such as

Order`[[System.Byte,mscorelib,Version=,PublicKeyToken=xxxxxx], [System.Int32,mscorelib,Version=]]

If the type has 4 Generic parameters , The just


In short, the ` The next number is the number of generic parameters , Brackets are a list of types .

If you don't know how to write , Let me tell you something , It's simple , Don't have to remember , Gets the name of the type Type, Look at it again FullName The attributes are known . As for that “`” character , It's in the upper left corner of the keyboard , Numbers 1 The one on the left . Look at the picture

The final generated code is shown in the figure below .

What about? , It's exciting .


Let's talk about a new one CodeDom My friend has a headache —— How to add members to enumeration types .

You just treat enumeration members as fields OK 了 , Take an example .

 CodeTypeDeclaration entype = new CodeTypeDeclaration("CloseMode");
// Specifies that it is an enumeration type
entype.IsEnum = true;
// Add members
CodeMemberField m1 = new CodeMemberField();
m1.Name = "Restart";
CodeMemberField m2 = new CodeMemberField();
m2.Name = "Shutdown";
CodeMemberField m3 = new CodeMemberField();
m3.Name = "None";
entype.Members.Add(m3); CodeDomProvider prd = CodeDomProvider.CreateProvider("cs");
prd.GenerateCodeFromType(entype, Console.Out, null);

This enumeration has three members , For enumeration , The type of the field may not be set , Just set the name of the member , Anyway, you want to , The members of the enumeration are int, At most byte、short these , It's all integer , therefore , As long as there are members' names .

The results are as follows .

If you want to assign specific values to some members , You can set InitExpression attribute . Such as this

 CodeMemberField m1 = new CodeMemberField();
m1.Name = "Restart";
m1.InitExpression = new CodePrimitiveExpression();

such , The generated enumeration members have values .

well , Today, Lao Zhou introduced to you the generation of type member code , It basically covers the attributes 、 Field 、 Methods and events . That's all , Too much is hard to digest .

I'll be free some other day , Lao Zhou continues to talk with us CodeDom.

【.net Deep breathing 】 Elaborate CodeDom(5): More articles on type members

  1. 【.net Deep breathing 】 Elaborate CodeDom(4): The type definition

    The last article talked about the namespace , Guess what to say next . Yes. , Below the namespace is the type , You know how to generate the definition code for a namespace , Then it's time to learn how to declare types . CLR There are usually several types of : class . Interface . structure . enumeration . entrust . That's it ...

  2. 【.net Deep breathing 】 Elaborate CodeDom(7): Indexer

    Before we get to the point , Let's add a little bit to the previous content . In the method , If you want to reference method parameters , In the previous example , Lao Zhou uses CodeVariableReferenceExpression class , It's used to refer to variables , It can also be used to refer to methods ...

  3. 【.net Deep breathing 】 Elaborate CodeDom(1): Structure view

    CodeDom What is it ?Html Dom Have you heard of it ,XML Dom Have you heard of it .DOM It can be translated as Document object model , that Code + DOM Well , Naturally, it refers to the code document model . If you've never touched it CodeDom, You probably ...

  4. F2 The intersection of workflow engine participant type members 、 and 、 Calculation rules of mutual disassembly

          Calculation description : Calculation rules refer to and others “ Participant type member ” Calculation between , Only when the processor is not empty can the rule be calculated , each “ Participant type member ” Execute in sequence of serial number . Calculation algorithm : Combine ( Lowest weight ), intersection ( In weight ) ...

  5. NET Design code II : Type member design next → .NET Design specification I : Basis of design code   Last one , Let's look at the types ...

  6. C++ static、const and static const Type member variable declaration and initialization

    C++ static.const and static const  And their initialization const The space of a defined constant will be released after it exceeds its scope , and static The defined static constant does not release its storage space after the function is executed . sta ...

  7. 【.net Deep breathing 】 Elaborate CodeDom(6): Method parameter

    In this paper, we will introduce the generation of method parameter code . Before we start , First of all, I want to add the content of the last bad article . In the last article , Lao Zhou reviewed MemberAttributes The use of enumeration , Lao Zhou mistakenly thought that the enumeration could not be bitwise ...

  8. 【.net Deep breathing 】 Elaborate CodeDom(3): Namespace

    In the last article , Lao Zhou introduced expressions and statements , Although Lao Zhou didn't tell all the contents once again , But I believe you have at least mastered the basic usage . In this paper , Let's go on CodeDom The secret of science and technology , This time, let's talk about namespace . Before we start , Old week ...

  9. 【.net Deep breathing 】 Elaborate CodeDom(9): Dynamic compilation

    You know, if you build code documentation , You know how to generate code , So it's easy to compile an assembly . CodeDomProvider Class provides three methods to perform compilation : 1.CompileAssemblyFromSource—— This ...

Random recommendation

  1. android Time Format

  2. Windows Phone 8.0 SDK Update(10322) Released

    Yesterday, Microsoft released a low-key WP 8 SDK Update , Even in Windows Phone Developer Blog It's not mentioned on the Internet . From a developer's point of view , This update really doesn't have much to pay attention to , Because no new one was added API and ...

  3. grunt install 、 To configure 、 stay webstrom Use in

    1. Global installation Grunt Command line (CLI) npm install -g grunt-cli Grunt CLI The task is very simple : Invocation and Gruntfile In the same directory Grunt. The advantage of this is , allow ...

  4. js The algorithm problem in , The ones you see all the time

    js There are not many algorithmic problems , It can be said that the basic encounter . But during the interview , Especially some big companies , There are always algorithms like this and that , Examine the logical thinking ability of a programmer . as follows : 1. Palindrome . Palindrome refers to putting the same words or sentences , Change places or ...

  5. IntelliJ IDEA Export database data in different formats

    Right click on the contents of the data table , First select in the pop-up window Data Extractor SQL Inserts, The secondary menu lists the types of exported data , Choose here SQL Inserts And then choose Dump Data Menu To Fi ...

  6. maven Configuration error JAVA_HOME not found in your environment

    It's quite empty recently , I want to study it spring mvc, So the development environment is configured step by step according to the tutorial . To configure maven After completion , Run the command mvn -v When , It's a mistake . The error message is as follows : Error: JAVA_HOME not fo ...

  7. Kernel module filp-&gt;open Reading and writing files 【 turn 】

    from : Usually the network part of things touch more , I didn't know how to write this at the beginning , Because definitely and in use ...

  8. ssh Environment variable problem of connecting remote host to execute script

    Recently in use ssh command ssh user@remote ~/ Log in to the remote machine remote When you execute a script on the , I have a strange problem : ~/ line n: app: co ...

  9. java Network programming TCP agreement java Servers and clients java socket Programming

    One HelloWord Grade Java Socket Examples of communication . Communication process :         Start... First Server End , Enter a dead loop to monitor whether there are connection requests on a port all the time . And then run Client End , customer ...

  10. Data Preprocess

    This paper attempts to solve a problem , That is, how to train the model with our custom data ? Get to know and learn , We come into contact with handwritten numeral recognition models , But the batch data is mnist Defined , We now have our own pictures of how to make batch training models . Now we will be ready for the original ...