Inside Microsoft® Visual Studio® .NET 2003 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Inside Microsoft® Visual Studio® .NET 2003 [Electronic resources] - نسخه متنی

Brian Johnson

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










Generating Code


In this section, we'll explore the active side of the code modelgenerating code. In most uses of the code model, code discovery isn't an end unto itself; instead, finding a source code element is just the first step toward changing that code element in some way. Conceptually, generating code with the code model is simplicity itself: you find the code element you want to modify, and then you call the appropriate Addxxx method to add a child code element or call a Removexxx method to delete a child code element. The devil is in the disassembly, however, and the code-generating methods have quirks to spare in each of the language implementations. The rest of this section provides an up-to-date reference on what does and doesn't work.

Note

The documentation claims that all the code model languages recognize fully qualified type names that use the dot (.) operator; in truth, the Visual C++ implementation understands only type names that use the double-colon [::] scope resolution operator. As a rule, if you pass a type name that uses the dot operator to a Visual C++ code model Addxxx method, Visual C++ adds the name as is, which results in syntactically incorrect source code.


Common Parameters


Most of the Addxxx methods have a few parameters in common. To not repeat each of these parameters in the following sections, we'll list the parameters most often used and give each a generic description. We'll refer to these parameters in the following sections only if there's additional information specific to the method being discussed.


Name

A string value that represents the name of the code construct. The Visual C++ implementation verifies the legality of the names you use, but the other languages use the name as is, which means it's up to you to make sure the name is valid. You can validate a name for a particular language by using the CodeModel.IsValidID method.


Type

The Type parameter governs the new code construct's type. This value takes either a CodeTypeRef object or a vsCMTypeRef enumeration value and sometimes a string containing a fully qualified type name. Be aware that some implementations substitute aliases for the types you give. For example, in the AddFunction method, even if you specify a function's return value as "System.Int32" or "System.Boolean", C# generates a return type of int or bool, respectively.


Position

The Position parameter determines where the new code element is placed in the source file relative to its sibling code elements. A value of 0 indicates that the new code element appears before any other sibling code elements, and a value of 1 indicates that the new code element appears after all other sibling code elements. To place a new code element after a particular sibling code element, you either pass in the sibling's CodeElements index or pass in a CodeElement that represents the sibling code element. (As of this version of Visual Studio .NET, none of the languages supports passing a CodeElement to the Position parameter.)


Access

The Access parameter controls the accessibility of the new code element. This parameter takes on one of the vsCMAccess enumeration values listed in Table A-14. The different implementations won't verify the appropriateness of the access you give a code element, so it's up to you to do so.



CodeModel Variations


If you skim the Visual Studio .NET Help, you'll notice that the Addxxx methods come in two flavors, which Help calls Variant1 and Variant2. A better description would be to call one set the "CodeModel variants"the CodeModel object isn't associated with any particular source file, so the CodeModel Addxxx methods have an extra Location parameter that specifies which file receives the generated code.

The name you pass to the Location parameter doesn't have to reference an existing file; if the file can't be found, a new one is created, so long as the name isn't an invalid filename. The most important thing to remember about the Location value is that it has to specify a correct source file for whatever language you're working with. (For example, "myfile.cpp" for Visual C++, "myfile.cs" for C#, and so on.) We'll ignore the CodeModel variants in the sections that follow.


Main Add Methods


This section describes the behavior of the code model methods that create the most basic code constructs, such as namespaces, classes, functions, and so on.


AddNamespace


The AddNamespace method applies to the CodeModel, FileCodeModel, and CodeNamespace objects and has the following prototype:


CodeNamespace AddNamespace(
string Name,
object Position
);

Note that you can create nested namespaces only by using the CodeNamespace object; the CodeModel and FileCodeModel objects can create top-level namespaces only. Otherwise, there's not really anything more to sayAddNamespace is about as straightforward a method as you'll find in the code model. Be thankful.


AddClass and AddStruct


The AddClass and AddStruct methods apply to the CodeModel, FileCodeModel, CodeNamespace, CodeClass, and CodeStruct objects and have the following prototypes:


CodeClass AddClass(
string Name,
object Position,
object Bases,
object ImplementedInterfaces,
vsCMAccess Access
);
CodeStruct AddStruct(
string Name,
object Position,
object Bases,
object ImplementedInterfaces,
vsCMAccess Access
);

The Bases parameter allows you to specify one or more base types for the new class or structure by passing in a 1-based array of CodeClass objects representing the bases. (The Visual C++ implementation also allows you to pass in an array of strings containing type names.) Of course, the common language runtime (CLR) doesn't support multiple implementation inheritance, so if you're generating managed code, you'll want to restrict yourself to a single base type. Currently, only the Visual C++ implementation supports the Bases parameter.

The ImplementedInterfaces parameter lets you add one or more interfaces to the class or structure's list of inherited types. ImplementedInterfaces takes a 1-based array of CodeInterface objects representing the interfaces to implement. As with the Bases parameter, the Visual C++ implementation also allows an array of strings representing type names. Only Visual C++ supports the ImplementedInterfaces parameter.


AddInterface


The AddInterface method applies to the CodeModel, FileCodeModel, and CodeNamespace objects and has the following prototype:


CodeInterface AddInterface(
string Name,
object Position,
object Bases,
vsCMAccess Access
);

The Bases parameter adds one or more interfaces to the new interface's list of inherited types. Bases takes a 1-based array of CodeInterface objects or strings representing the interfaces to implement. None of the implementations supports the Bases parameter, but you can achieve the same functionality in some of the implementations by using the CodeInterface.AddBase method.


AddDelegate


The AddDelegate method applies to the CodeModel, FileCodeModel, CodeNamespace, CodeClass, and CodeStruct objects and has the following prototype:


CodeDelegate AddDelegate(
string Name,
object Type,
object Position,
vsCMAccess Access
);

Currently, only C# implements this method.


AddFunction


The AddFunction method applies to the CodeModel, FileCodeModel, CodeClass, CodeStruct, and CodeInterface objects and has the following prototype:


CodeFunction AddFunction(
string Name,
vsCMFunction Kind,
object Type,
object Position,
vsCMAccess Access,
);

The Name parameter controls the name of the function, except in the case of constructors and destructors (which take the name of the class to which they belong).

The Kind parameter determines what kind of function to create, such as a constructor or pure virtual function. This parameter takes one or more of the constants from the vsCMFunction enumeration, which are listed in Table A-32. Not every combination of vsCMFunction values is meaningful; even so, some implementations do their best to create a "getter constructor" when asked, so it's up to you to ensure that the value you pass to AddFunction makes sense.


AddProperty


The AddProperty method applies to the CodeClass, CodeInterface, and CodeStruct objects and has the following prototype:


CodeProperty AddProperty(
string GetterName,
string PutterName,
object Type,
object Position,
vsCMAccess Access,
object Location
);

Currently, only the C# AddProperty implementation works. The GetterName and PutterName parameters represent the names of the property getter and property setter, respectively. For a C# read/write property, the GetterName and PutterName values must be the same. You can create a read-only property by passing null to the PutterName parameter and create a write-only property by passing null to the GetterName parameter.

The Location parameter allows you to specify a new file into which this property will go; it has the same semantics as the CodeModel-variant Location parameters. (See the section titled "CodeModel Variations.") The C# implementation ignores this parameter.


AddEnum


The AddEnum method applies to the CodeModel, FileCodeModel, CodeNamespace, CodeClass, and CodeStruct objects and has the following prototype:


CodeEnum AddEnum(
string Name,
object Position,
object Bases,
vsCMAccess Access
);

The Bases parameter takes a 1-based array of CodeType objects or strings representing the underlying type of the enumeration. None of the implementations uses the Bases parameter.


AddVariable


The AddVariable method applies to the CodeModel, FileCodeModel, CodeClass, and CodeStruct objects and has the following prototype:


CodeVariable AddVariable(
string Name,
object Type,
object Position,
vsCMAccess Access
);

The AddVariable method works for all implementations, but because C# and J# don't allow top-level variable declarations, the CodeModel.AddVariable and FileCodeModel.AddVariable methods for these languages throw exceptions.


AddAttribute


The AddAttribute method applies to the CodeModel, FileCodeModel, CodeClass, CodeDelegate, CodeEnum, CodeFunction, CodeInterface, CodeParameter, CodeProperty, CodeStruct, CodeVariable, and CodeType objects (did we leave any out?) and has the following prototype:


CodeAttribute AddAttribute(
string Name,
string Value,
object Position
);

Currently, C# and J# don't implement AddAttribute. The Visual C++ CodeDelegate and CodeProperty objects are read-only and won't allow you to add an attribute. Of the writable Codexxx objects that Visual C++ supports, only the CodeParameter object doesn't implement AddAttribute.


Other Add Methods


This section describes the remainder of the code model add methods, which allow you to flesh out the basic constructs created by the add methods in the previous section.


AddBase


The AddBase method applies to the CodeClass, CodeStruct, CodeDelegate, CodeInterface, CodeEnum, and CodeType objects and has the following prototype:


CodeElement AddBase(
object Base,
object Position
);

The Base parameter represents the new base type for the particular object; in the case of a C# CodeEnum, the Base parameter represents the underlying type of the enumeration. (Currently, the C# CodeEnum.AddBase implementation is broken.)

Each of the languages implements AddBase in its own special way; Table A-37 summarizes the combinations of language, object, and base type. (It doesn't make sense to add a new base to a delegate, so you won't find an implementation of CodeDelegate.AddBase in any of the languages.)

Table A-37. Valid Types for the AddBase Method's Base Parameter


Visual C++


Visual C#


Visual J#


CodeClass.AddBase





CodeClass


No


Yes


Yes


CodeInterface


No


No


No


CodeTypeRef


No


Yes


Yes


CodeType


No


Yes


Yes


Fully qualified name


Yes


Yes


Yes


CodeStruct.AddBase





CodeClass


No


No


N/A


CodeInterface


No


Yes


N/A


CodeTypeRef


No


No


N/A


CodeType


No


No


N/A


Fully qualified name


Yes


Yes


N/A


CodeInterface.AddBase





CodeClass


No


No


N/A


CodeInterface


No


Yes


N/A


CodeTypeRef


No


Yes


N/A


CodeType


No


Yes


N/A


Fully qualified name


Yes


Yes


N/A


CodeEnum.AddBase





CodeClass


N/A


N/A


N/A


CodeInterface


N/A


N/A


N/A


CodeTypeRef


N/A


N/A


N/A


CodeType


N/A


N/A


N/A


Fully qualified name


N/A


N/A


N/A


AddImplementedInterface


The AddImplementedInterface method applies to the CodeClass and CodeStruct objects and has the following prototype:


CodeInterface AddImplementedInterface(
object Base,
object Position
);

The Base parameter takes either a CodeInterface object or a string with a fully qualified type name representing the interface that the class or structure will implement. Only J# implements this method.


AddMember


The AddMember method applies to the CodeEnum object and has the following prototype:


CodeVariable AddMember(
string Name,
object Value,
object Position
);

You use this method to add a new member to an enumeration. The Name parameter becomes the name of the new member, and the Value parameter becomes the initial value of the member. You can pass a numeric value to the Value parameter using either a string or an object and the method will insert the correct operator for the member's initialization; however, it's up to you to ensure the validity of the member's value.


AddParameter


The AddParameter method applies to the CodeDelegate and CodeFunction objects and has the following prototype:


CodeParameter AddParameter(
string Name,
object Type,
object Position
);

The AddParameter method doesn't allow you to create optional parameters.


CreateArrayType


The CreateArrayType method applies to the CodeTypeRef object and has the following prototype:


CodeTypeRef CreateArrayType(
int Rank
);

This method returns a CodeTypeRef that you can use to create an array. The Rank parameter determines the number of dimensions in the array described by the new CodeTypeRef. Here's an example of how to use this method to create a new array (assuming you have a CodeModel reference in the cdeModel variable and a CodeClass reference in the cdeClass variable):


Dim cdeVariable As CodeVariable
Dim cdeTypeRef As CodeTypeRef
Dim cdeTypeRefArray As CodeTypeRef
' Create a reference to an int type
cdeTypeRef = cdeModel.CreateCodeTypeRef(vsCMTypeRef.vsCMTypeRefInt)
' Turn the reference into an int array type
cdeTypeRefArray = cdeTypeRef.CreateArrayType()
' Create a new int array variable within a class
cdeVariable = cdeClass.AddVariable("myIntArray", cdeTypeRefArray)

Currently, none of the languages supports this method.


Remove Methods


This section describes the code model methods that allow you to rid your source code of unwanted code constructs.


Delete


The Delete method applies to the CodeAttribute object and has the following prototype:


void Delete();

None of the languages supports this method.


Remove


The Remove method applies to the CodeModel, FileCodeModel, and CodeNamespace objects and has the following prototype:


void Remove(
object Element
);

The Element parameter takes either a CodeElement or CodeType. The C# and J# implementations remove the corresponding source code from the file; the Visual C++ implementation takes a more conservative approach and simply comments out the code elementthe one exception being the CodeParameter object, which Visual C++ deletes.

In C# and J#, only the identifier of a CodeVariable is deleted, which can be a little awkward when all that's left of your declaration is object;.


RemoveBase


The RemoveBase method applies to the CodeClass, CodeDelegate, CodeEnum, CodeInterface, CodeStruct, and CodeType objects and has the following prototype:


void RemoveBase(
object Element
);

The RemoveBase method is the inverse of the AddBase method. The Element parameter takes a CodeElement representing the base to remove. (The C# implementation also allows a CodeType for this parameter.) Note that RemoveBase won't let you remove System.Object if it's the only base class.

For C# enumerations, CodeEnum.RemoveBase worksbut barely. As with the AddBase method, the C# CodeEnum.RemoveBase method takes a 1-based array of CodeType or CodeTypeRef objects that represents the underlying type of the enumeration.


RemoveInterface


The RemoveInterface method applies to the CodeClass and CodeStruct objects and has the following prototype:


void RemoveInterface(
object Element
);

The Element parameter takes a CodeInterface object representing the interface to remove from the ImplementedInterfaces collection. Only J# implements this method.


RemoveMember


The RemoveMember method applies to the CodeClass, CodeDelegate, CodeEnum, CodeInterface, CodeStruct, and CodeType objects and has the following prototype:


void RemoveMember(
object Element
);

The Element parameter takes a CodeElement representing the child code construct to remove. A RemoveMember has no meaning for the CodeDelegate object because a delegate never has elements in its Members collection.


RemoveParameter


The RemoveParameter method applies to the CodeDelegate and CodeFunction objects and has the following prototype:


void RemoveParameter(
object Element
);

The Element parameter takes a CodeParameter object representing the parameter to remove from the corresponding delegate or function. Only C# and J# implement this method.


/ 118