65.9K
CodeProject 正在变化。 阅读更多。
Home

CodeDom 中常用的 .NET 编码模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (50投票s)

2005 年 11 月 1 日

13分钟阅读

viewsIcon

185630

downloadIcon

738

一套 CodeDom 模板库,包含 .NET 中常用的编码实践。

目录

引言

CLR 和其他 .NET 代码包含许多重复出现的模式。当这些模式出现在代码中时,它们也可能出现在 CodeDom 图生成的代码中,但生成这些模式需要大量重复的工作。该库包含许多模式实现,可供您自己的 CodeDom 生成器使用,有助于将您编写的代码量减少 **数千行**。
如果您认为有某个模式非常适合此库,请留下评论,很有可能在下一个版本中就会提供。

截至 2006 年 10 月 23 日,该项目托管在 CodePlex 上,本文档旨在介绍其功能。

参数断言模式

参数断言模式是 CLR 中重复出现的模式,用于检查参数并相应地引发 `ArgumentNullException` 等异常。当前支持的断言包括:`NotNull`、`InRange`、`InLowerBound`、`InUpperBound`、`IsInstanceOf`、`EnumIsDefined` 和 `StringNotNullOrEmpty`。

要将此模式包含在您的代码中,您的代码应如下所示:

myMethod.Statements.Add(
    new CodePatternArgumentAssertNotNullStatement("myArgument"));
myMethod.Statements.Add(
    new CodePatternArgumentAssertInRangeStatement("myArgument",
        new CodeFieldReferenceExpression(
            new CodeTypeReferenceExpression("MyType"), "MinValue"), 
        new CodeFieldReferenceExpression(
            new CodeTypeReferenceExpression("MyType"), "MaxValue")));
myMethod.Statements.Add(
    new CodePatternArgumentAssertIsInstanceOfStatement(
                                         "myArgument", typeof(int)));

上述代码生成的将是:

if ((myArgument == null))
{
    throw new System.ArgumentNullException("myArgument");
}
if (((myArgument > MyType.MaxValue) 
    || (myArgument < MyType.MinValue)))
{
    throw new System.ArgumentOutOfRangeException("myArgument");
}
if ((myArgument.GetType().IsInstanceOfType(typeof(int)) == false))
{
    throw new System.ArgumentException(string.Format(
              "The argument myArgument must be of type {0}.", 
              typeof(int).FullName), "myArgument");
}

程序集信息模式

由 Visual Studio 自动添加的程序集可以通过一组特性来识别。此模式简化了对派生自 `CodeCompileUnit` 的类的这些特性的属性访问。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternCompileUnit unit = new CodePatternCompileUnit();
unit.AssemblyVersion = new Version(1, 0);
unit.AssemblyTitle = "My assembly";
unit.CLSCompliant = true;

上述代码生成的将是:

[assembly: System.Reflection.AssemblyVersionAttribute("1.0")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0")]
[assembly: System.Reflection.AssemblyTitleAttribute("My assembly")]
[assembly: System.CLSCompliantAttribute(true)]

异步操作模式

异步方法调用是 CLR 中一个反复出现的模式,许多系统和组件都需要它。此处提供的实现是最简单的,它使用委托。可以通过 `HasComments` 属性来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternAsyncOperation(myMethod));

上述代码生成的将是:

/// <summary>

/// Represents the delegate instance

/// for asynchronous calls to MyMethod.

/// </summary>

private MyMethodAsyncCallback m_MyMethodCallback;

/// <summary>

/// Executes the MyMethod method asynchronously with a callback.

/// </summary>

/// <param name="foo">See original method, MyMethod,

/// for more information about this parameter.</param>

/// <param name="callback">A method to be called when

/// the asynchronous action completes.</param>

/// <returns>An <see cref="System.IAsyncResult" />

/// object detailing the asynchronous action.</returns>

public System.IAsyncResult BeginMyMethod(int foo, 
                           System.AsyncCallback callback)
{
    if ((this.m_MyMethodCallback == null))
    {
        this.m_MyMethodCallback = 
                new MyMethodAsyncCallback(this.MyMethod);
    }
    return this.m_MyMethodCallback.BeginInvoke(foo, callback, null);
}

/// <summary>

/// Executes the MyMethod method asynchronously.

/// </summary>

/// <param name="foo">See original method, MyMethod,

/// for more information about this parameter.</param>

/// <returns>An <see cref="System.IAsyncResult" />

/// object detailing the asynchronous action.</returns>

public System.IAsyncResult BeginMyMethod(int foo)
{
    return this.BeginMyMethod(foo, null);
}

/// <summary>

/// Synchronously completes an asynchronous call to MyMethod.

/// </summary>

/// <param name="asyncResult">The <see cref="System.IAsyncResult" />

/// retrieved from the call to <see cref="BeginMyMethod" />.</param>

/// <exception cref="System.InvalidOperationException">Thrown

/// when the method is called before the

/// <see cref="BeginMyMethod" /> method.</exception>

public void EndMyMethod(System.IAsyncResult asyncResult)
{
    if ((this.m_MyMethodCallback == null))
    {
        throw new System.InvalidOperationException("End of asynchronous" + 
                  " operation attempted when one has not yet begun.");
    }
    this.m_MyMethodCallback.EndInvoke(asyncResult);
}

/// <summary>

/// Represents the delegate for asynchronous calls to MyMethod.

/// </summary>

public delegate void MyMethodAsyncCallback(int foo);

BeginProcess/EndProcess 模式

来自 `System.Data` 和 `System.Windows.Forms` 的一个重复模式是 BeginProcess/EndProcess 模式,例如 `BeginLoad`/`EndLoad` 和 `BeginInit`/`EndInit`。此模式通过直观的接口实现事件的静默。可以通过 `HasComments` 属性来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternBeginEndProcess("Init"));

上述代码生成的将是:

/// <summary>

/// See <see cref="IsInInit" />

/// for information about this field.

/// </summary>

private int m_IsInInit;

/// <summary>

/// Begins the Init process.

/// </summary>

public virtual void BeginInit()
{
    this.m_IsInInit = (this.m_IsInInit + 1);
}

/// <summary>

/// Ends the Init process.

/// </summary>

public virtual void EndInit()
{
    if ((this.m_IsInInit != 0))
    {
        this.m_IsInInit = (this.m_IsInInit - 1);
    }
}

/// <summary>

/// Gets whether the Init process has begun.

/// </summary>

/// <value>Whether the init process has begun.</value>

protected bool IsInInit()
{
    return (this.m_IsInInit != 0);
}

二元运算符模式

大多数二元运算符都内置在 CodeDom 中,但有些没有。此模式扩展了标准的 `CodeBinaryOperatorExpression` 以添加更多运算符。当前支持的运算符:`BooleanExclusiveOr`。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.Add(
    new CodeConditionStatement(
        new CodePatternBinaryOperatorExpression(
           new CodeVariableReferenceExpression("bool1"), 
           CodePatternBinaryOperatorType.BooleanExclusiveOr,
           new CodeVariableReferenceExpression("bool2"))
        /* , Contained statements */));

上述代码生成的将是:

if (((bool1 == true) && (bool2 == false)) || 
                ((bool1 == false) && (bool2 == true)))
{
    // Contained statements...

}

代码访问安全装饰器模式

声明式代码访问安全模型在 CLR 中非常普遍,并且在许多不同的情况下都非常重要。

要将此模式包含在您的代码中,您的代码应如下所示:

UI ui = new DotNetZen.CodeDom.Patterns.Permissions.UI();
ui.Clipboard = 
  System.Security.Permissions.UIPermissionClipboard.AllClipboard;
myMethod.CustomAttributes.Add(new CodePatternCasAttribute(ui));

上述代码生成的将是:

[System.Security.Permissions.UIPermissionAttribute(
   System.Security.Permissions.SecurityAction.Demand, 
   Clipboard=System.Security.Permissions.
             UIPermissionClipboard.AllClipboard)]
private void MyMethod()
{
}
目前支持所有框架的声明式 CAS 特性,并且可以通过继承 `DotNetZen.CodeDom.Patterns.Permissions.Permission` 来轻松创建自定义特性抽象。

复合赋值模式

CodeDom 中没有内置复合赋值运算符。此模式扩展了标准的 `CodeAssignStatement` 以添加更多运算符。当前支持的运算符:`Add`、`Subtract`、`Multiply`、`Divide`、`Modulus`、`BitwiseAnd`、`BitwiseOr`。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.Add(
    new CodePatternCompoundAssignStatement(
        new CodeVariableReferenceExpression("foo"),
        CodePatternCompoundAssignmentOperatorType.Add,
        new CodeVariableReferenceExpression("bar")));

上述代码生成的将是:

foo = (foo + bar);

光标锁定模式

来自 `System.Windows.Forms` 的一个重复模式是锁定 `Form` 的 `Cursor` 属性。当其中包含的进程时间较长时,此模式非常有用。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.AddRange(
    new CodePatternCursorLock(/* Contained statements */));

上述代码生成的将是:

System.Windows.Forms.Cursor cursor0 = this.Cursor;

try
{
    this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
    
    // More code here...

}
finally
{
    this.Cursor = cursor0;
}

自定义特性模式

大多数自定义特性都派生自相同的模板。因此,创建自定义特性可能是一项繁琐的任务。可以通过 `HasComments` 属性和 `SetComment` 方法来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternCustomAttributeDeclaration attrib = 
      new CodePatternCustomAttributeDeclaration(
          "CoolMetaData",
          AttributeTargets.Struct | 
             AttributeTargets.Class | AttributeTargets.Enum,
          false, true,
          new CodeParameterDeclarationExpression(typeof(int), 
                                               "MetaData"));

attrib.SetComment("MetaData", "The metadata for the attribute");

上述代码生成的将是:

[System.AttributeUsageAttribute(((System.AttributeTargets.Enum | 
                                  System.AttributeTargets.Struct) 
        | System.AttributeTargets.Class), 
        AllowMultiple=false, Inherited=true)]
public sealed class CoolMetaDataAttribute : System.Attribute
{
    /// <summary>

    /// Value for the property <see cref="MetaData" />.

    /// </summary>

    private int m_MetaData;

    /// <summary>

    /// Initializes a new instance of the

    /// <see cref="CoolMetaDataAttribute" /> class.

    /// </summary>

    public CoolMetaDataAttribute()
    {
    }

    /// <summary>

    /// Initializes a new instance of the

    /// <see cref="CoolMetaDataAttribute" /> class.

    /// </summary>

    /// <param name="MetaData">The metadata

    /// for the attribute.</param>

    public CoolMetaDataAttribute(int MetaData)
    {
        this.m_MetaData = MetaData;
    }

    /// <summary>

    /// Gets the metadata for the attribute.

    /// </summary>

    /// <value>The metadata for the attribute.</value>

    public int MetaData
    {
        get
        {
            return this.m_MetaData;
        }
    }
}

自定义异常模式

大多数自定义异常都派生自相同的模板。因此,创建自定义异常可能是一项繁琐的任务。可以通过 `HasComments` 属性和 `SetComment` 方法来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternCustomExceptionDeclaration exception = 
    new CodePatternCustomExceptionDeclaration("Foo",
        new CodeParameterDeclarationExpression(
                               typeof(int), "Bar"));

exception.SetComment("Bar", "A healthy snack-bar");

上述代码生成的将是:

[System.SerializableAttribute()]
public class FooException : System.Exception
{
    /// <summary>

    /// Value for the property <see cref="Bar" />.

    /// </summary>

    private int m_Bar;

    /// <summary>

    /// Initializes a new instance of the <see cref="FooException" /> class.

    /// </summary>

    /// <param name="Bar">A healthy snack-bar.</param>

    public FooException(int Bar)
    {
        this.m_Bar = Bar;
    }

    /// <summary>

    /// Initializes a new instance of the <see cref="FooException" /> class.

    /// </summary>

    /// <param name="Bar">A healthy snack-bar.</param>

    /// <param name="message">The message in the exception.</param>

    public FooException(int Bar, string message) : 
        base(message)
    {
        this.m_Bar = Bar;
    }

    /// <summary>

    /// Initializes a new instance of the <see cref="FooException" /> class.

    /// </summary>

    /// <param name="info">The data needed to serialize

    /// or deserialize an object.</param>

    /// <param name="context">The source and destination

    /// of a given serialized stream.</param>

    /// <remarks>This member supports the .NET Framework infrastructure

    /// and is not intended to be used directly from your code.</remarks>

    protected FooException(System.Runtime.Serialization.SerializationInfo info, 
              System.Runtime.Serialization.StreamingContext context) : 
              base(info, context)
    {
        this.m_Bar = ((int)(info.GetValue("m_Bar", typeof(int))));
    }

    /// <summary>

    /// Initializes a new instance of the <see cref="FooException" /> class.

    /// </summary>

    /// <param name="Bar">A healthy snack-bar.</param>

    /// <param name="message">The message in the exception.</param>

    /// <param name="innerException">An exception

    /// encapsulated in the new exception.</param>

    public FooException(int Bar, string message, 
           System.Exception innerException) : 
           base(message, innerException)
    {
        this.m_Bar = Bar;
    }

    /// <summary>

    /// Gets a healthy snack-bar.

    /// </summary>

    /// <value>A healthy snack-bar.</value>

    public int Bar
    {
        get
        {
            return this.m_Bar;
        }
    }

    /// <summary>

    /// Populates a <see
    /// cref="System.Runtime.Serialization.SerializationInfo" />

    /// with the data needed to serialize the target object.

    /// </summary>

    /// <param name="info">The <see 
    ///      cref="System.Runtime.Serialization.SerializationInfo" />

    /// to populate with data.</param>

    /// <param name="context">The destination

    /// (see <see cref="System.Runtime.Serialization.StreamingContext" />)

    /// for this serialization.</param>

    /// <exception cref="System.ArgumentNullException">Thrown when

    /// the <paramref name="info" /> parameter is a null reference

    /// (Nothing in Visual Basic).</exception>

    [System.Security.Permissions.SecurityPermissionAttribute(
        System.Security.Permissions.SecurityAction.LinkDemand, 
        Flags=System.Security.Permissions.
              SecurityPermissionFlag.SerializationFormatter)]
    public override void GetObjectData(
                    System.Runtime.Serialization.SerializationInfo 
                    info, 
                    System.Runtime.Serialization.StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("m_Bar", this.m_Bar, typeof(int));
    }
}

委托模式

委托模式,也称为事件处理程序模式,是 CLR 中一个重复出现的模式,其中使用具有专门的 `EventArgs` 类的 `object` 和 `EventArgs` 来创建委托。此模式对于快速创建任何委托都很有用。可以通过 `HasComments` 属性和 `SetComment` 方法来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternDelegate delegateType = new CodePatternDelegate(
    "ItemChanged",
    new CodeParameterDeclarationExpression(typeof(int), "OldValue"),
    new CodeParameterDeclarationExpression(typeof(int), "NewValue"));

delegateType.SetComment("OldValue", "The value before the change");
delegateType.SetComment("NewValue", "The value after the change");

nameSpace.Types.AddRange(delegateType);

上述代码生成的将是:

/// <summary>

/// Represents a method that takes a <see cref="System.Object" />

/// and <see cref="ItemChangedEventArgs" />.

/// </summary>

/// <param name="sender">The event's originating object.</param>

/// <param name="e">The event's arguments.</param>

public delegate void ItemChangedEventHandler(object sender, 
                                    ItemChangedEventArgs e);

/// <summary>

/// Contains the arguments for events based

/// on the <see cref="ItemChangedEventHandler" /> delegate.

/// </summary>

public class ItemChangedEventArgs : System.EventArgs
{
    
    /// <summary>

    /// Value for the property <see cref="OldValue" />.

    /// </summary>

    private int m_OldValue;
    
    /// <summary>

    /// Value for the property <see cref="NewValue" />.

    /// </summary>

    private int m_NewValue;
    
    /// <summary>

    /// Initializes a new instance of the

    /// <see cref="ItemChangedEventArgs" /> class.

    /// </summary>

    /// <param name="OldValue">The value before the change.</param>

    /// <param name="NewValue">The value after the change.</param>

    public ItemChangedEventArgs(int OldValue, int NewValue)
    {
        this.m_OldValue = OldValue;
        this.m_NewValue = NewValue;
    }
    
    /// <summary>

    /// Gets the value before the change.

    /// </summary>

    /// <value>The value before the change.</value>

    public virtual int OldValue
    {
        get
        {
            return this.m_OldValue;
        }
    }
    
    /// <summary>

    /// Gets the value after the change.

    /// </summary>

    /// <value>The value after the change.</value>

    public virtual int NewValue
    {
        get
        {
            return this.m_NewValue;
        }
    }
}

可 Dispose 类型模式

这是一个 CLR 中推荐使用的模式,用于 `IDisposable` 接口,以防止在对象已处置时运行终结器。可以通过 `automaticComments` 参数来控制生成成员的文档。
要在派生自已实现此模式的类型的类型中实现该模式,请使用 `DisposeImplementationType.Inherited` 值,并且只会生成 `void Dispose(bool)` 的重写。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternTypeDeclaration declaration = 
            new CodePatternTypeDeclaration("MyType");
// ...

declaration.ApplyDisposablePattern(
     new CodeInstanceReferenceExpression(new 
     CodeFieldReferenceExpression(new CodeThisReferenceExpression(), 
     "myReferenceTypeField"), typeof(object)), 
     new CodeInstanceReferenceExpression(new 
     CodeFieldReferenceExpression(new CodeThisReferenceExpression(), 
     "myValueTypeField"), typeof(int)));

上述代码生成的将是:

public class MyType : System.IDisposable
{
    /// <summary>

    /// Releases all resources used by the object.

    /// </summary>

    public void Dispose()
    {
        this.Dispose(true);
        System.GC.SuppressFinalize(this);
    }

    /// <summary>

    /// Releases the unmanaged resources used by the object

    /// and optionally releases the managed resources.

    /// </summary>

    /// <param name="disposing">true to release both managed

    /// and unmanaged resources; false

    /// to release only unmanaged resources.</param>

    /// <remarks>This method is called by the public

    /// <see cref="Dispose()" /> method and the Finalize method.

    /// <see cref="Dispose" /> invokes the protected

    /// <see cref="Dispose(System.Boolean)" /> method with

    /// the <paramref name="disposing" /> parameter set to true.

    /// Finalize invokes Dispose with

    /// <paramref name="disposing" /> set to false.

    /// When the <paramref name="disposing" /> parameter is true,

    /// this method releases all resources held

    /// by any managed objects that this object references.

    /// This method invokes the <see cref="Dispose()" />

    /// method of each referenced object.

    /// Notes to Inheritors: This method can be called multiple times

    /// by other objects. When overriding it, be careful not to reference

    /// objects that have been previously

    /// disposed of in an earlier call.</remarks>

    protected virtual void Dispose(bool disposing)
    {
        if ((disposing == true))
        {
            if ((this.myReferenceTypeField != null))
            {
                ((System.IDisposable)(this.myReferenceTypeField)).Dispose();
            }
            ((System.IDisposable)(this.myValueTypeField)).Dispose();
        }
    }
}

请注意,由于 .NET Framework 中的一个 bug,无法创建终结器!请在 LadyBug 上为这个问题投票

事件模式

事件模式是 `System.Windows.Forms` 中一个重复出现的模式,其中事件具有特殊的调用方法。此模式对于快速创建任何事件都很有用。可以通过 `HasComments` 属性来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternEvent(
    "EventHappened", Scope.Instance, typeof(EventHandler)));

上述代码生成的将是:

public event System.EventHandler EventHappened;

/// <summary>

/// Raises the <see cref="EventHappened" /> event.

/// </summary>

/// <param name="e">The value passed

/// for the event's e parameter.</param>

protected virtual int OnEventHappened(System.EventArgs e)
{
    if ((this.EventHappened != null))
    {
        this.EventHappened(this, e);
    }
}

请注意,由于 .NET Framework 中的一个 bug,无法生成 `static` 事件!请在 LadyBug 上为这个问题投票

语言限制:Visual Basic 不允许事件返回值。

Flags 模式

Flags 模式是整个 CLR 中一个重复出现的模式,其中使用 `FlagsAttribute` 特性标记 `enum`。此模式自动分配值,并支持多达 63 个值。
可以使用 `Flags` 索引器访问每个成员的 `CodeMemberField` 对象。

要将此模式包含在您的代码中,您的代码应如下所示:

nameSpace.Types.Add(new CodePatternFlags("MyFlags", 
                                      "A", "B", "C"));

上述代码生成的将是:

[System.FlagsAttribute()]
public enum MyFlags : int
{
    A = 1,
    B = 2,
    C = 4,
}

ForEach 模式

ForEach 模式内置于 C# 中,但并非 IL 的原生支持。该模式遍历实现 `System.IEnumerable` 接口的集合。如 C# 规范所述,不需要实现该接口,但需要实现 `MoveNext` 和 `GetEnumerator` 等方法。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.AddRange(new CodePatternForEach(
    new CodeTypeReference(typeof(int)), 
    new CodeVariableReferenceExpression("myCollection"),
    new CodeTypeReference("EnumeratorType")
    /* , Contained statements */));

上述代码生成的将是:

System.Collections.IEnumerator enumerator0 = 
  ((System.Collections.IEnumerator)(myCollection)).GetEnumerator();

try
{
    for (; enumerator0.MoveNext();)
    {
        int element0 = ((int)(enumerator0.Current));
        // Contained statements ...

    }
}
finally
{
    if (((enumerator0 != null) && 
          enumerator0.GetType().IsInstanceOfType(
                      typeof(System.IDisposable))))
    {
        ((System.IDisposable)(enumerator0)).Dispose();
    }
}

Get 属性/字段模式

Get 属性/字段模式是整个 CLR 中一个重复出现的模式,其中使用具有 `get` 访问器的属性来公开 `private` 字段。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternGetField("Value", 
    new CodeTypeReference(typeof(int)), Scope.Instance));

上述代码生成的将是:

private int m_Value;

public int Value
{
    get
    {
        return this.m_Value;
    }
}

Is Instance Of 模式

Is Instance Of 模式在 C# 中作为 `is` 关键字内置,并且也是 IL 的原生支持,但它并未在 CodeDom 中实现。该模式检查对象的类型是否实现、继承或等于查询的类型。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.Add(new CodePatternIsInstExpression(
          new CodeVariableReferenceExpression("myVariable"),
          new CodeTypeReference(typeof(IMyInterface))));

上述代码生成的将是:

myVariable.GetType().IsInstanceOfType(typeof(IMyInterface))

锁定模式

锁定模式内置于 C# 中,但并非 IL 的原生支持。该模式使用 `System.Threading.Monitor` 类锁定资源。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.AddRange(new CodePatternLock(
          new CodeFieldReferenceExpression(
               new CodeThisReferenceExpression(), "SyncRoot")
          /* , Contained statements... */));

上述代码生成的将是:

object lockCachedExpr0 = this.SyncRoot;
System.Threading.Monitor.Enter(lockCachedExpr0);

try
{
    // Contained statements...

}
finally
{
    System.Threading.Monitor.Exit(lockCachedExpr0);
}

可 Null 值类型属性模式

可 Null 值类型属性模式在 CLR 1.x(泛型和 Nullable<T> 之前)中使用,用于表示具有 null 值的类型属性。此模式主要在强类型数据集 (`Typed DataSets`) 中使用。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternNullableProperty("Value", 
         new CodeTypeReference(typeof(int)), Scope.Instance));

上述代码生成的将是:

private int m_Value;

/// <summary>

/// See <see cref="IsValueNull" /> for information about this field.

/// </summary>

private bool m_IsValueNull = true;

public int Value
{
    get
    {
        if ((this.m_IsValueNull == true))
        {
            throw new System.InvalidOperationException("Can not" + 
                  " get value when it is null. Check for " + 
                  "nullability by calling IsValueNull.");
        }
        return this.m_Value;
    }
    set
    {
        this.m_Value = value;
        this.m_IsValueNull = false;
    }
}

/// <summary>

/// Gets whether the value of <see cref="Value" /> is null.

/// </summary>

/// <value>Whether the value of <see cref="Value" /> is null.</value>

public bool IsValueNull
{
    get
    {
        return this.m_IsValueNull;
    }
}

/// <summary>

/// Sets the value of <see cref="Value" /> to null.

/// </summary>

public void SetValueNull()
{
    this.m_IsValueNull = true;
}

观察者模式

观察者模式是一个经典模式,它允许订阅者收到值更改的通知。此实现允许通过事件来宣布属性值的更改。可以通过 `HasComments` 属性来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

type.Members.AddRange(new CodePatternObserver("MyValue", 
    new CodeTypeReference(typeof(int)), Scope.Instance));

上述代码生成的将是:

/// <summary>

/// Value for the property <see cref="MyValue" />.

/// </summary>

private int m_MyValue;

public int MyValue
{
    get
    {
        return this.m_MyValue;
    }
    set
    {
        if ((this.m_MyValue != value))
        {
            int oldValue = this.m_MyValue;
            this.m_MyValue = value;
            this.OnMyValueChanged(new MyValueChangedEventArgs(oldValue, 
                                                        this.m_MyValue));
        }
    }
}

/// <summary>

/// Occurs when the <see cref="MyValue" /> property is changed.

/// </summary>

public event MyValueChangedEventHandler MyValueChanged;

/// <summary>

/// Raises the <see cref="MyValueChanged" /> event.

/// </summary>

/// <param name="e">The value passed

/// for the event's e parameter.</param>

protected virtual void OnMyValueChanged(MyValueChangedEventArgs e)
{
    if ((this.MyValueChanged != null))
    {
        this.MyValueChanged(this, e);
    }
}

/// <summary>

/// Represents a method that takes a <see cref="System.Object" />

/// and <see cref="MyValueChangedEventArgs" />.

/// </summary>

/// <param name="sender">The event's originating object.</param>

/// <param name="e">The event's arguments.</param>

public delegate void MyValueChangedEventHandler(object sender, 
                                   MyValueChangedEventArgs e);

/// <summary>

/// Contains the arguments for events based

/// on the <see cref="MyValueChangedEventHandler" /> delegate.

/// </summary>

public class MyValueChangedEventArgs : System.EventArgs
{
    /// <summary>

    /// Value for the property <see cref="OldValue" />.

    /// </summary>

    private int m_OldValue;

    /// <summary>

    /// Value for the property <see cref="NewValue" />.

    /// </summary>

    private int m_NewValue;

    /// <summary>

    /// Initializes a new instance

    /// of the <see cref="MyValueChangedEventArgs" /> class.

    /// </summary>

    /// <param name="OldValue">The value before the change.</param>

    /// <param name="NewValue">The current value.</param>

    public MyValueChangedEventArgs(int OldValue, int NewValue)
    {
        this.m_OldValue = OldValue;
        this.m_NewValue = NewValue;
    }

    /// <summary>

    /// Gets the value before the change.

    /// </summary>

    /// <value>The value before the change.</value>

    public virtual int OldValue
    {
        get
        {
            return this.m_OldValue;
        }
    }

    /// <summary>

    /// Gets the current value.

    /// </summary>

    /// <value>The current value.</value>

    public virtual int NewValue
    {
        get
        {
            return this.m_NewValue;
        }
    }
}

可序列化类型模式

这是 CLR 中的一个模式,它应用了框架中的四种不同类型的序列化之一:对于新序列化类型和继承序列化类型的类型,有 `Basic`、`Selective` 和 `Custom`。可以通过 `automaticComments` 参数来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

CodePatternTypeDeclaration declaration = 
                     new CodePatternTypeDeclaration("MyType");
decl.Members.Add(new CodeMemberField(typeof(int), "myField"));
decl.ApplySerializablePattern(SerializationType.NewCustom, "myField");

上述代码生成的将是:

[System.SerializableAttribute()]
public class MyType : System.Runtime.Serialization.ISerializable
{
    private int myField;

    /// <summary>

    /// Initializes a new instance of the <see cref="MyType" /> class.

    /// </summary>

    /// <param name="info">The data needed

    /// to serialize or deserialize an object.</param>

    /// <param name="context">The source

    /// and destination of a given serialized stream.</param>

    /// <remarks>This member supports the .NET Framework

    /// infrastructure and is not intended

    /// to be used directly from your code.</remarks>

    protected MyType(System.Runtime.Serialization.SerializationInfo info, 
              System.Runtime.Serialization.StreamingContext context)
    {
        this.myField = ((int)(info.GetValue("myField", typeof(int))));
    }

    /// <summary>

    /// Populates a <see cref="System.Runtime.Serialization.
    ///                        SerializationInfo" />

    /// with the data needed to serialize the target object.

    /// </summary>

    /// <param name="info">The <see 
    /// cref="System.Runtime.Serialization.SerializationInfo" />

    /// to populate with data.</param>

    /// <param name="context">The destination (see <see 
    /// cref="System.Runtime.Serialization.StreamingContext" />)

    /// for this serialization.</param>

    /// <exception cref="System.ArgumentNullException">Thrown

    /// when the <paramref name="info" /> parameter is a null

    /// reference (Nothing in Visual Basic).</exception>

    [System.Security.Permissions.SecurityPermissionAttribute(
        System.Security.Permissions.SecurityAction.LinkDemand, 
        Flags=System.Security.Permissions.
              SecurityPermissionFlag.SerializationFormatter)]
    public virtual void GetObjectData(
           System.Runtime.Serialization.SerializationInfo 
           info, System.Runtime.Serialization.StreamingContext context)
    {
        if ((info == null))
        {
            throw new System.ArgumentNullException("info");
        }
        info.AddValue("myField", this.myField, typeof(int));
    }
}

单例模式

单例模式是一个经典模式,它允许一个类在应用程序中只有一个实例。此实现遵循最佳实践,并且是线程安全的。它还允许惰性加载或预加载实现。可以通过 `HasComments` 属性来控制生成成员的文档。

要将此模式包含在您的代码中,您的代码应如下所示:

nameSpace.Types.Add(new CodePatternSingleton("Foo", 
                                   LoadType.LazyLoad));

上述代码生成的将是:

public class Foo
{
    private Foo()
    {
    }

    /// <summary>

    /// Gets the single instance of type <see cref="Foo" />.

    /// </summary>

    /// <value>The single instance of type <see cref="Foo" />.</value>

    public static Foo Instance
    {
        get
        {
            return InstanceContainer.Instance;
        }
    }

    class InstanceContainer
    {
        private static Foo m_Instance = new Foo();

        static InstanceContainer()
        {
        }

        private InstanceContainer()
        {
        }

        public static Foo Instance
        {
            get
            {
                return InstanceContainer.m_Instance;
            }
        }
    }
}

强类型集合模式

强类型集合模式是实现完全强类型化的一种麻烦。这是最常见的类型模式之一,也是可能拥有 1001 种不同实现的模式之一。此实现包括可选事件(在加载数据时可以静默它们)、完整的 `IList` 实现以及额外的便捷构造函数和方法,如 `AddRange` 和 `ToArray`。

要将此模式包含在您的代码中,您的代码应如下所示:

nameSpace.Types.Add(new CodePatternTypedCollection(
                      typeof(int), CollectionEvents.All));

上述代码生成的将是:

/// <summary>

/// Represents a collection of <see cref="Int32" /> elements.

/// </summary>

[System.SerializableAttribute()]
public class Int32Collection : System.Collections.CollectionBase
{
    /// <summary>

    /// See <see cref="IsInLoad" /> for information about this field.

    /// </summary>

    private int m_IsInLoad;
    
    /// <summary>

    /// Initializes a new instance

    /// of the <see cref="Int32Collection" /> class.

    /// </summary>

    public Int32Collection()
    {
    }
    
    /// <summary>

    /// Initializes a new instance of the

    /// <see cref="Int32Collection" /> class.

    /// </summary>

    /// <param name="values">A list of objects of type

    /// <see cref="Int32" /> to initialize

    /// the collection with.</param>

    public Int32Collection(params int[] values)
    {
        if ((values == null))
        {
            throw new System.ArgumentNullException("values");
        }
        this.InnerList.Capacity = values.Length;
        this.BeginLoad();
        try
        {
            this.AddRange(values);
        }
        finally
        {
            this.EndLoad();
        }
    }
    
    /// <summary>

    /// Initializes a new instance of the

    /// <see cref="Int32Collection" /> class.

    /// </summary>

    /// <param name="collection">An object of type

    /// <see cref="Int32Collection" /> containing

    /// objects to be copied into the new collection.</param>

    public Int32Collection(Int32Collection collection)
    {
        if ((collection == null))
        {
            throw new System.ArgumentNullException("collection");
        }
        this.InnerList.Capacity = collection.Count;
        this.BeginLoad();
        try
        {
            this.AddRange(collection);
        }
        finally
        {
            this.EndLoad();
        }
    }
    
    /// <summary>

    /// Gets or sets the <see cref="Int32" />

    /// at position <paramref name="index" />.

    /// </summary>

    /// <value>The <see cref="Int32" /> at position

    /// <paramref name="index" />.</value>

    /// <param name="index">The position

    /// of the <see cref="Int32" />.</param>

    public int this[int index]
    {
        get
        {
            return ((int)(this.List[index]));
        }
        set
        {
            this.List[index] = value;
        }
    }
    
    /// <summary>

    /// Gets an object that can be used

    /// to synchronize access to the collection.

    /// </summary>

    /// <value>An object that can be used to synchronize

    /// access to the collection.</value>

    public object SyncRoot
    {
        get
        {
            return this.List.SyncRoot;
        }
    }
    
    /// <summary>

    /// Occurs when the collection begins

    /// the process of removing all elements.

    /// </summary>

    /// <remarks>To indicate that clearing the collection

    /// is not possible, throw an exception

    /// from an attached method.</remarks>

    public event System.EventHandler Clearing;
    
    /// <summary>

    /// Occurs after the collection completes

    /// the process of removing all elements.

    /// </summary>

    public event System.EventHandler Cleared;
    
    /// <summary>

    /// Occurs when the collection begins

    /// the process of inserting an element.

    /// </summary>

    /// <remarks>To indicate that inserting this element is invalid,

    /// throw an exception from an attached method. To indicate

    /// that the element is simply invalid, use the

    /// <see cref="Validating" /> event.</remarks>

    public event EventHandler Inserting;
    
    /// <summary>

    /// Occurs after the collection completes

    /// the process of inserting an element.

    /// </summary>

    /// <remarks>To prevent the insertion from taking place,

    /// throw an exception from an attached method.</remarks>

    public event EventHandler Inserted;
    
    /// <summary>

    /// Occurs when the collection begins

    /// the process of removing an element.

    /// </summary>

    /// <remarks>To indicate that removing this element is invalid,

    /// throw an exception from an attached method. To indicate that

    /// the element is simply invalid, use the

    /// <see cref="Validating" /> event.</remarks>

    public event EventHandler Removing;
    
    /// <summary>

    /// Occurs after the collection completes

    /// the process of removing an element.

    /// </summary>

    /// <remarks>To prevent the removal from taking place,

    /// throw an exception from an attached method.</remarks>

    public event EventHandler Removed;
    
    /// <summary>

    /// Occurs when the collection begins the process

    /// of setting an element at a certain position.

    /// </summary>

    /// <remarks>To indicate that setting this element

    /// at this position is invalid, throw an exception from an attached

    /// method. To indicate that the element is simply invalid,

    /// use the <see cref="Validating" /> event.</remarks>

    public event SetEventHandler Setting;
    
    /// <summary>

    /// Occurs after the collection completes the process

    /// of setting an element at a certain position.

    /// </summary>

    /// <remarks>To prevent the settng action from taking

    /// place, throw an exception from an attached method.</remarks>

    public event SetEventHandler Set;
    
    /// <summary>

    /// Occurs when the collection asks for validation

    /// of an item that is to be added into it.

    /// </summary>

    /// <remarks>If the item is invalid,

    /// throw an exception from an attached method.

    /// Checks that already take place are that the value is not a null

    /// reference (Nothing in Visual Basic) and that it is of/derives

    /// from <see cref="Int32" />.</remarks>

    public event ValidationEventHandler Validating;
    
    /// <summary>

    /// Begins the Load process.

    /// </summary>

    public virtual void BeginLoad()
    {
        this.m_IsInLoad = (this.m_IsInLoad + 1);
    }
    
    /// <summary>

    /// Ends the Load process.

    /// </summary>

    public virtual void EndLoad()
    {
        if ((this.m_IsInLoad != 0))
        {
            this.m_IsInLoad = (this.m_IsInLoad - 1);
        }
    }
    
    /// <summary>

    /// Gets whether the Load process has begun.

    /// </summary>

    /// <value>Whether the Load process has begun.</value>

    protected bool IsInLoad()
    {
        return (this.m_IsInLoad != 0);
    }
    
    /// <summary>

    /// Inserts an element into the collection at the specified index.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// <paramref name="value" /> should be inserted.</param>

    /// <param name="value">The <see cref="Int32" /> to insert.</param>

    /// <exception cref="System.ArgumentOutOfRangeException">

    /// <paramref name="index" /> is less than zero or is greater

    /// than <see cref="System.Collections.CollectionBase.Count" />.

    /// </exception>

    public void Insert(int index, int value)
    {
        this.List.Insert(index, value);
    }
    
    /// <summary>

    /// Removes the first occurrence of a specific

    /// <see cref="Int32" /> from the collection.

    /// </summary>

    /// <param name="value">The <see cref="Int32" />

    /// to remove from the collection.</param>

    public void Remove(int value)
    {
        this.List.Remove(value);
    }
    
    /// <summary>

    /// Determines whether an element is in the collection.

    /// </summary>

    /// <param name="value">The <see cref="Int32" />

    /// to locate in the collection.</param>

    /// <returns>true if <paramref name="value" />

    /// is found in the collection; otherwise, false.</returns>

    public bool Contains(int value)
    {
        return this.List.Contains(value);
    }
    
    /// <summary>

    /// Searches for the specified <see cref="Int32" />

    /// and returns the zero-based index of the first

    /// occurrence within the entire collection.

    /// </summary>

    /// <param name="value">The <see cref="Int32" />

    /// to locate in the collection.</param>

    /// <returns>The zero-based index of the first occurrence

    /// of <paramref name="value" /> within the entire collection,

    /// if found; otherwise, -1.</returns>

    public int IndexOf(int value)
    {
        return this.List.IndexOf(value);
    }
    
    /// <summary>

    /// Adds an object to the end of the collection.

    /// </summary>

    /// <param name="value">The <see cref="Int32" />

    /// to be added to the end of the collection.</param>

    /// <returns>The collection index at which the

    /// <paramref name="value" /> has been added.</returns>

    public int Add(int value)
    {
        return this.List.Add(value);
    }
    
    /// <summary>

    /// Adds the elements of an array to the end of the collection.

    /// </summary>

    /// <param name="values">The array whose elements should be

    /// added to the end of the collection.</param>

    /// <exception cref="System.ArgumentNullException">

    /// <paramref name="values" /> is a null reference

    /// (Nothing in Visual Basic).</exception>

    public void AddRange(int[] values)
    {
        if ((values == null))
        {
            throw new System.ArgumentNullException("values");
        }
        System.Collections.IEnumerator enumerator0 = 
           ((System.Collections.IEnumerable)(values)).GetEnumerator();
        try
        {
            for (
                ; (enumerator0.MoveNext() == true); 
                )
            {
                int element0 = ((int)(enumerator0.Current));
                this.List.Add(element0);
            }
        }
        finally
        {
            if (((enumerator0 != null) 
                && enumerator0.GetType().IsInstanceOfType(
                   typeof(System.IDisposable))))
            {
                ((System.IDisposable)(enumerator0)).Dispose();
            }
        }
    }
    
    /// <summary>

    /// Adds the elements of a collection to the end of the collection.

    /// </summary>

    /// <param name="collection">The collection whose elements

    /// should be added to the end of the collection.</param>

    /// <exception cref="System.ArgumentNullException">

    /// <paramref name="collection" /> is a null reference

    /// (Nothing in Visual Basic).</exception>

    public void AddRange(Int32Collection collection)
    {
        if ((collection == null))
        {
            throw new System.ArgumentNullException("collection");
        }
        System.Collections.IEnumerator enumerator1 = 
           ((System.Collections.IEnumerable)
            (collection.InnerList)).GetEnumerator();
        try
        {
            for (
                ; (enumerator1.MoveNext() == true); 
                )
            {
                int element1 = ((int)(enumerator1.Current));
                this.List.Add(element1);
            }
        }
        finally
        {
            if (((enumerator1 != null) 
                && enumerator1.GetType().IsInstanceOfType(
                   typeof(System.IDisposable))))
            {
                ((System.IDisposable)(enumerator1)).Dispose();
            }
        }
    }
    
    /// <summary>

    /// Copies the entire collection to a compatible one-dimensional

    /// <see cref="System.Array" />, starting at the specified

    /// <paramref name="index" /> of the target array.

    /// </summary>

    /// <param name="array">The one-dimensional

    /// <see cref="System.Array" />

    /// that is the destination of the elements copied from collection.

    /// The <see cref="System.Array" /> must

    /// have zero-based indexing.</param>

    /// <param name="index">The zero-based index in <paramref
    /// name="array" /> at which copying begins.</param>

    /// <exception cref="System.ArgumentNullException"><paramref
    /// name="array" /> is a null reference

    /// (Nothing in Visual Basic).</exception>

    /// <exception cref="System.ArgumentOutOfRangeException">

    /// <paramref name="index" /> is less than zero.</exception>

    /// <exception cref="System.ArgumentException"><paramref
    /// name="array" /> is multidimensional.</exception>

    /// <exception cref="System.ArgumentException">

    /// <paramref name="index" />

    /// is equal to or greater than the length

    /// of <paramref name="array" />.</exception>

    /// <exception cref="System.ArgumentException">The number

    /// of elements in the source collection

    /// is greater than the available space

    /// from <paramref name="index" /> to the end of the destination

    /// <paramref name="array" />.</exception>

    /// <remarks>The specified array's elements must be of type

    /// <see cref="Int32" /> or any of its derivatives.</remarks>

    public void CopyTo(System.Array array, int index)
    {
        this.List.CopyTo(array, index);
    }
    
    /// <summary>

    /// Copies the elements of the collection

    /// to a new <see cref="Int32" /> array.

    /// </summary>

    /// <returns>An array of <see cref="Int32" /> containing

    /// copies of the elements of the collection.</returns>

    public int[] ToArray()
    {
        return ((int[])(this.InnerList.ToArray(typeof(Int32))));
    }
    
    /// <summary>

    /// Raises the <see cref="Clearing" /> event.

    /// </summary>

    protected override void OnClear()
    {
        if (((this.IsInLoad() == false) 
            && (this.Clearing != null)))
        {
            this.Clearing(this, System.EventArgs.Empty);
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Cleared" /> event.

    /// </summary>

    protected override void OnClearComplete()
    {
        if (((this.IsInLoad() == false) 
            && (this.Cleared != null)))
        {
            this.Cleared(this, System.EventArgs.Empty);
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Inserting" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// to insert <paramref name="value" />.</param>

    /// <param name="value">The new value of the element

    /// at <paramref name="index" />.</param>

    protected override void OnInsert(int index, object value)
    {
        if (((this.IsInLoad() == false) 
            && (this.Inserting != null)))
        {
            this.Inserting(this, new EventArgs(index, ((int)(value))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Inserted" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// to insert <paramref name="value" />.</param>

    /// <param name="value">The new value of the element

    /// at <paramref name="index" />.</param>

    protected override void OnInsertComplete(int index, object value)
    {
        if (((this.IsInLoad() == false) 
            && (this.Inserted != null)))
        {
            this.Inserted(this, new EventArgs(index, ((int)(value))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Removing" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// <paramref name="value" /> can be found.</param>

    /// <param name="value">The value of the element to remove

    /// from <paramref name="index" />.</param>

    protected override void OnRemove(int index, object value)
    {
        if (((this.IsInLoad() == false) 
            && (this.Removing != null)))
        {
            this.Removing(this, new EventArgs(index, 
                         ((int)(value))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Removed" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// <paramref name="value" /> can be found.</param>

    /// <param name="value">The value of the element

    /// to remove from <paramref name="index" />.</param>

    protected override void OnRemoveComplete(int index, object value)
    {
        if (((this.IsInLoad() == false) 
            && (this.Removed != null)))
        {
            this.Removed(this, new EventArgs(index, 
                        ((int)(value))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Setting" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// <paramref name="oldValue" /> can be found.</param>

    /// <param name="oldValue">The value to replace

    /// with <paramref name="newValue" />.</param>

    /// <param name="newValue">The new value of the

    /// element at <paramref name="index" />.</param>

    protected override void OnSet(int index, 
              object oldValue, object newValue)
    {
        if (((this.IsInLoad() == false) 
            && (this.Setting != null)))
        {
            this.Setting(this, new SetEventArgs(index, 
                        ((int)(oldValue)), ((int)(newValue))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Set" /> event.

    /// </summary>

    /// <param name="index">The zero-based index at which

    /// <paramref name="oldValue" /> can be found.</param>

    /// <param name="oldValue">The value to replace

    /// with <paramref name="newValue" />.</param>

    /// <param name="newValue">The new value of the element

    /// at <paramref name="index" />.</param>

    protected override void OnSetComplete(int index, 
              object oldValue, object newValue)
    {
        if (((this.IsInLoad() == false) 
            && (this.Set != null)))
        {
            this.Set(this, new SetEventArgs(index, 
                    ((int)(oldValue)), ((int)(newValue))));
        }
    }
    
    /// <summary>

    /// Raises the <see cref="Validating" /> event.

    /// </summary>

    /// <param name="value">The object to validate.</param>

    protected override void OnValidate(object value)
    {
        base.OnValidate(value);
        if ((value.GetType().IsInstanceOfType(typeof(int)) == false))
        {
            throw new System.ArgumentException(
                  string.Format("The argument" + 
                  " value must be of type {0}.", 
                  typeof(int).FullName), "value");
        }
        if (((this.IsInLoad() == false) 
            && (this.Validating != null)))
        {
            this.Validating(this, 
                new ValidationEventArgs(((int)(value))));
        }
    }
    
    /// <summary>

    /// Represents a method that takes a <see cref="System.Object" />

    /// and <see cref="EventArgs" />.

    /// </summary>

    /// <param name="sender">The event's originating object.</param>

    /// <param name="e">The event's arguments.</param>

    public delegate void EventHandler(object sender, EventArgs e);
    
    /// <summary>

    /// Contains the arguments for events based

    /// on the <see cref="EventHandler" /> delegate.

    /// </summary>

    public class EventArgs : System.EventArgs
    {
        /// <summary>

        /// Value for the property <see cref="Index" />.

        /// </summary>

        private int m_Index;
        
        /// <summary>

        /// Value for the property <see cref="Value" />.

        /// </summary>

        private int m_Value;
        
        /// <summary>

        /// Initializes a new instance

        /// of the <see cref="EventArgs" /> class.

        /// </summary>

        /// <param name="Index">The index of the value.</param>

        /// <param name="Value">The value raised by the event.</param>

        public EventArgs(int Index, int Value)
        {
            this.m_Index = Index;
            this.m_Value = Value;
        }
        
        /// <summary>

        /// Gets the index of the value.

        /// </summary>

        /// <value>The index of the value.</value>

        public virtual int Index
        {
            get
            {
                return this.m_Index;
            }
        }
        
        /// <summary>

        /// Gets the value raised by the event.

        /// </summary>

        /// <value>The value raised by the event.</value>

        public virtual int Value
        {
            get
            {
                return this.m_Value;
            }
        }
    }
    
    /// <summary>

    /// Represents a method that takes a

    /// <see cref="System.Object" />

    /// and <see cref="SetEventArgs" />.

    /// </summary>

    /// <param name="sender">The event's originating object.</param>

    /// <param name="e">The event's arguments.</param>

    public delegate void SetEventHandler(object sender, 
                                         SetEventArgs e);
    
    /// <summary>

    /// Contains the arguments for events based on the

    /// <see cref="SetEventHandler" /> delegate.

    /// </summary>

    public class SetEventArgs : System.EventArgs
    {
        /// <summary>

        /// Value for the property <see cref="Index" />.

        /// </summary>

        private int m_Index;
        
        /// <summary>

        /// Value for the property <see cref="OldValue" />.

        /// </summary>

        private int m_OldValue;
        
        /// <summary>

        /// Value for the property <see cref="NewValue" />.

        /// </summary>

        private int m_NewValue;
        
        /// <summary>

        /// Initializes a new instance of the

        /// <see cref="SetEventArgs" /> class.

        /// </summary>

        /// <param name="Index">The zero-based index

        /// at which oldValue can be found.</param>

        /// <param name="OldValue">The value

        /// to replace with newValue.</param>

        /// <param name="NewValue">The new value

        /// of the element at index.</param>

        public SetEventArgs(int Index, int OldValue, int NewValue)
        {
            this.m_Index = Index;
            this.m_OldValue = OldValue;
            this.m_NewValue = NewValue;
        }
        
        /// <summary>

        /// Gets the zero-based index at which oldValue can be found.

        /// </summary>

        /// <value>The zero-based index at which

        /// oldValue can be found.</value>

        public virtual int Index
        {
            get
            {
                return this.m_Index;
            }
        }
        
        /// <summary>

        /// Gets the value to replace with newValue.

        /// </summary>

        /// <value>The value to replace with newValue.</value>

        public virtual int OldValue
        {
            get
            {
                return this.m_OldValue;
            }
        }
        
        /// <summary>

        /// Gets the new value of the element at index.

        /// </summary>

        /// <value>The new value of the element at index.</value>

        public virtual int NewValue
        {
            get
            {
                return this.m_NewValue;
            }
        }
    }
    
    /// <summary>

    /// Represents a method that takes a <see cref="System.Object" />

    /// and <see cref="ValidationEventArgs" />.

    /// </summary>

    /// <param name="sender">The event's originating object.</param>

    /// <param name="e">The event's arguments.</param>

    public delegate void ValidationEventHandler(object sender, 
                                        ValidationEventArgs e);
    
    /// <summary>

    /// Contains the arguments for events based

    /// on the <see cref="ValidationEventHandler" /> delegate.

    /// </summary>

    public class ValidationEventArgs : System.EventArgs
    {
        /// <summary>

        /// Value for the property <see cref="Value" />.

        /// </summary>

        private int m_Value;
        
        /// <summary>

        /// Initializes a new instance of the

        /// <see cref="ValidationEventArgs" /> class.

        /// </summary>

        /// <param name="Value">The value to be validated.</param>

        public ValidationEventArgs(int Value)
        {
            this.m_Value = Value;
        }
        
        /// <summary>

        /// Gets the value to be validated.

        /// </summary>

        /// <value>The value to be validated.</value>

        public virtual int Value
        {
            get
            {
                return this.m_Value;
            }
        }
    }
}

请注意,.NET Framework 2.0 及之前版本中的一个 bug 不允许创建参数数组,这意味着在这些版本中使用此模式是不完整的。

一元运算符模式

CodeDom 中没有内置一元运算符。此模式扩展了标准的 `CodeBinaryOperatorExpression` 以添加更多运算符。当前支持的运算符:`BooleanNot`、`BooleanIsTrue`、`IsNull`、`NotNull`。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.Add(
    new CodeConditionStatement(
        new CodePatternBinaryOperatorExpression(
            CodePatternUnaryOperatorType.BooleanNot,
            new CodeVariableReferenceExpression("bool1"))
        /* , Contained statements */));

上述代码生成的将是:

if (bool1 == false)
{
    // Contained statements...

}

Using 模式

Using 模式内置于 C# 中,但并非 IL 的原生支持。该模式使用实现 `System.IDisposable` 接口的资源,然后释放它。

要将此模式包含在您的代码中,您的代码应如下所示:

method.Statements.AddRange(new CodePatternUsing(
    new CodeVariableDeclarationStatement(
                typeof(System.Drawing.Image), "image"),
    ResourceType.ReferenceType
    /* , Contained statements... */));

上述代码生成的将是:

System.Drawing.Image image;

try
{
    // Contained statements...

}
finally
{
    if ((image != null))
    {
        ((System.IDisposable)(image)).Dispose();
    }
}

XML 注释模式

XML 注释是编写描述性强且易于解析的成员注释的标准方法,可以使用 NDoc 等工具进行解析。当前支持的标签及其类等效项是:

  • <summary> - `SummaryStatements`。
  • <c> - `TextAsCodeExpression`。
  • <code> - `MultilineTextAsCodeStatements`。
  • <example> - `ExampleStatements`。
  • <exception> - `ExceptionStatements`。
  • <list> - `ListStatements`。
  • <para> - `ParagraphExpression`。
  • <param> - `ParameterStatements`。
  • <paramref> - `ParameterReferenceExpression`。
  • <remarks> - `RemarksStatements`。
  • <returns> - `ReturnsStatements`。
  • <see> - `SeeExpression`。
  • <seealso> - `SeeAlsoStatements`。
  • <value> - `ValueStatements`。
此外,还有几个模板:`CommentsForConstructor`、`CommentsForMethod`、`CommentsForProperty` 和 `CommentsForIndexer`。

顺便说一句,Microsoft 发布了 Sandcastle,但它尚未最终确定。一旦确定,将添加类来支持它提供的更高级功能。

历史

  • 2006-10-31 - 版本 1.8。
    1. 已添加代码访问安全装饰器模式。
    2. 已添加程序集信息模式。
    3. 在可序列化类型模式的 `GetObjectData` 中添加了安全声明。
    4. XML 注释模式已移至 `.Xml` 命名空间,并删除了 `CodeXmlComment` 前缀(太长)。
    5. 二进制文件现在以 .NET 2.0 而不是 .NET 1.1 为目标,但它们在大多数情况下仍向后兼容。
  • 2006-09-23:版本 1.7。
    1. 已添加可 Null 值类型属性模式。
    2. 已添加 `Enum.IsDefined` 和 `String.IsNullOrEmpty` 断言。
    3. 已添加可序列化类型模式。
    4. 可 Dispose 类型模式现已成为 `CodePatternTypeDeclaration` 的一部分。
  • 2006-04-29:版本 1.6。
    1. 已添加异步操作模式。
    2. 已添加可 Dispose 类型模式。
    3. 已添加 XML 注释模式。
    4. 对 Begin/End Process、自定义特性、自定义异常、委托、事件、观察者、单例和强类型集合模式进行了自动文档化。
    5. 已添加一元运算符 `IsNull` 和 `NotNull`。
    6. 现在可以在 Flags 模式中访问每个标志的 `CodeMemberField`。
    7. 单例模式(惰性加载)不再公开内部使用的 `InstanceContainer` 类。
    8. 已修复强类型集合模式的 `ToArray` 方法。
    9. 该作品现已获得 Creative Commons Attribution 2.5 许可。您可以复制、自由分发、衍生甚至在商业产品中使用代码,但必须归功于作者。
  • 2006-03-31:版本 1.5。
    1. 已添加强类型集合模式。
    2. 已添加参数断言模式。
    3. 程序集和所有类型现在都已 `CLSCompliant`。
    4. 所有类型现在都已标记为 `Serializable`。
    5. 自定义特性模式现在生成密封特性,以提高生成代码的效率。
    6. 添加了几个重载和错误修复。
  • 2006-02-10:版本 1.4。
    1. 与 Visual Basic 的生成兼容。
    2. 自定义异常模式已从接受 `CodePatternGetFields` 更改为接受 `CodeParameterDeclarationExpressions`。
    3. 事件模式现在有一个接受委托类型的重载(并推断参数和返回类型)。
    4. ForEach 模式现在按照 C# 规范工作。
    5. 修复了几个 bug。
  • 2006-01-28:版本 1.3。
    1. 程序集已重命名为 _DotNetZen.CodeDom.Patterns_。
    2. 已添加自定义特性模式。
    3. 已添加自定义异常模式。
  • 2006-01-13:版本 1.2。
    1. 已添加二元和一元运算符模式。
    2. 已添加复合赋值模式。
  • 2005-11-11:版本 1.1。
    1. 光标锁定模式现在会将光标改回其原始图标,而不是 `Cursors.Default`。
    2. 已添加 For Each 模式。
    3. 已添加 Is Instance Of 模式。
    4. 范围的布尔标志现在使用 `Scope` 枚举实现。
    5. Using 模式的资源类型的布尔标志现在使用 `ResourceType` 枚举实现。
    6. Singleton 模式的加载类型的布尔标志现在使用 `LoadType` 枚举实现。
  • 2005-10-30:初始发布。

Creative Commons License
本作品获得 Creative Commons Attribution 2.5 License 许可。
(可复制、分发、衍生、商业使用;必须署名作者)

© . All rights reserved.