{
codetypedeclaration col = new codetypedeclaration(
fortype.basetype + "collection" );
col.basetypes.add(typeof(collectionbase));
col.attributes = memberattributes.final | memberattributes.public;
// add method
codemembermethod add = new codemembermethod();
add.attributes = memberattributes.final | memberattributes.public;
add.name = "add";
add.returntype = new codetypereference(typeof(int));
add.parameters.add( new codeparameterdeclarationexpression (
fortype, "value" ) );
// generates: return base.innerlist.add(value);
add.statements.add( new codemethodreturnstatement (
new codemethodinvokeexpression(
new codepropertyreferenceexpression(
new codebasereferenceexpression(), "innerlist"),
"add",
new codeexpression[]
{ new codeargumentreferenceexpression( "value" ) }
)
)
);
// add to type.
col.members.add(add);
// indexer property ('this')
codememberproperty indexer = new codememberproperty();
indexer.attributes = memberattributes.final | memberattributes.public;
indexer.name = "item";
indexer.type = fortype;
indexer.parameters.add( new codeparameterdeclarationexpression (
typeof( int ), "idx" ) );
indexer.hasget = true;
indexer.hasset = true;
// generates: return (thetype) base.innerlist[idx];
indexer.getstatements.add(
new codemethodreturnstatement (
new codecastexpression(
fortype,
new codeindexerexpression(
new codepropertyreferenceexpression(
new codebasereferenceexpression(),
"innerlist"),
new codeexpression[]
{ new codeargumentreferenceexpression( "idx" ) } )
)
)
);
// generates: base.innerlist[idx] = value;
indexer.setstatements.add(
new codeassignstatement(
new codeindexerexpression(
new codepropertyreferenceexpression(
new codebasereferenceexpression(),
"innerlist"),
new codeexpression[]
{ new codeargumentreferenceexpression("idx") }),
new codeargumentreferenceexpression( "value" )
)
);
// add to type.
col.members.add(indexer);
return col;
}
此时,您应该考虑一个在对 codedom 进行编程时有用的技巧;看到这些似乎没完没了的 statements.add 代码行了吗?当然,我们可以将它们拆分为多个独立的行,每行创建一个临时变量以容纳该对象并将其传递给下一行。但这样只会使它们更加无穷无尽!那好,只要您能够习惯,那么下面的技巧会是一种将这些代码行拆分为多个部分的好方法:
要生成 codedom 嵌套语句,邻近的属性/索引器/方法访问通常是从右向左构建的。
实际上:要生成以下代码行:
base.innerlist[idx]
您应该从索引器表达式 [idx] 开始,接着是属性访问 innerlist,最后是对象引用基。这将生成下面的 codedom 嵌套语句:
codeexpression st = new codeindexerexpression(
new codepropertyreferenceexpression(
new codebasereferenceexpression(),
"innerlist"
),
new codeexpression[]
{ new codeargumentreferenceexpression( "idx" ) }
);
请注意,我从右向左创建语句,最后才完成适当的构造函数参数。用这种方式手动缩进和拆分代码行通常是一个好主意,这样可以更容易地看到各个对象构造函数在哪里结束以及哪些是它的参数。
最后,icodeextension.process 方法实现涉及到对类型及其字段进行迭代,以查找基于数组的字段:
public class arraystocollectionsextension : icodeextension
{
public void process( codenamespace code, xmlschema schema )
{
// copy as we will be adding types.
codetypedeclaration[] types =
new codetypedeclaration[code.types.count];
code.types.copyto( types, 0 );
foreach ( codetypedeclaration type in types )
{
if ( type.isclass || type.isstruct )
{
foreach ( codetypemember member in type.members )
{
// process fields only.
if ( member is codememberfield &&
( ( codememberfield )member ).type.arrayelementtype != null )
{
codememberfield field = ( codememberfield ) member;
codetypedeclaration col = getcollection(