CodeDom 中常用的 .NET 编码模式






4.80/5 (50投票s)
2005 年 11 月 1 日
13分钟阅读

185630

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