GridControl 주변에 전형적인 코드 조각이 있다고 가정 해보십시오.aspect와 필드 인젝션을 둘러싼 디자인 컨셉
private GridControl myGrid;
internal void InitialiseGrid()
{
myGrid.BeginUpdate();
try
{
....
}
finally
{
myGrid.EndUpdate();
}
}
지금은 최종 코드는 비슷하게 있도록 샛길에서 행동의 유형을 래핑하는 PostSharp 또는 무언가를 사용하고 싶다고 말할 수 : SO의 지속적인 반대 감안할 때
private GridControl myGrid;
[MyGridControlUpdateAspect(FieldName="myGrid")]
internal void InitialiseGrid()
{
....
}
및 리플렉션을 사용하여 클래스의 비공개 필드에 액세스하지 못하게하는 경우 다른 사용자가 myGrid에 액세스하고 aspect 소스 코드 내에서 BeginUpdate 및 EndUpdate 메소드를 호출하여 특정 그리드에 대한 참조가 전달 될 수있는 방식으로 더 나은 방법을 제공 할 수 있습니까? 어떤면에서 그 면면에, 그리고 여전히 순결 주의자들을 만족시킨다.
업데이트 : 다음은 메소드 입력시 커서를 변경하기 위해 try/finally 블록으로 싸여있는 코드의 실제 예입니다. 이 기능을 수행하는 측면을 활용함으로써 특정 코드 조각에이 기능을 특별히 추가하지 않고도이 기능을 많은 방법에 추가 할 수 있습니다.
[ChangeCursor(CursorPropertyName = "Cursor", NewCursorTypeName = "WaitCursor", AspectPriority = 8)]
internal void SomeButtonClick(object sender, System.EventArgs args)...
또는
[assembly: ChangeCursor(CursorPropertyName = "Cursor", NewCursorTypeName = "WaitCursor", AttributeTargetTypes = "SomeNamespace.*", AttributeTargetMembers = "regex:.*ButtonClick", AttributePriority = 30, AspectPriority = 12)]
화면 코드 (반사의 사용주의 -는 인스턴스 내의 필드가 아닌 실제 인스턴스를 사용하여이 경우에, 그러나 개념은 동일합니다).
/// <summary>
/// Aspect to set the cursor for a windows form to a particular
/// cursor type and reset it back to the default type on exit
/// </summary>
[Serializable]
[AttributeUsage(AttributeTargets.Method)]
[MulticastAttributeUsage(MulticastTargets.Method)]
public sealed class ChangeCursorAttribute : OnMethodBoundaryAspect
{
/// <summary>
/// The name of the property that will be available in the instance
/// of the method that this aspect advises.
/// <para>It is expected to derive from System.Windows.Forms but
/// does not necessarily have to provided it has a System.Windows.Form.Cursor property
/// that matches this name</para>
/// </summary>
public string CursorPropertyName { get; set; }
/// <summary>
/// The name of the cursor to set to a standard System.Windows.Forms.Cursors type
/// </summary>
public string NewCursorTypeName { get; set; }
/// <summary>
/// The type of the cursor to set on entry
/// </summary>
private Cursor NewCursorType { get; set; }
/// <summary>
/// The property info for the cursor property name
/// </summary>
private PropertyInfo CursorPropertyInfo { get; set; }
/// <summary>
/// The aspect is advising on an extension method
/// instead of a method in the class with the Cursors attribute
/// </summary>
private bool IsExtensionMethodAttribute { get; set; }
/// <summary>
/// Validate the necessary properties are set in the attribute at compile time
/// </summary>
/// <param name="method"></param>
/// <returns></returns>
public override bool CompileTimeValidate(MethodBase method)
{
if (CursorPropertyName == null)
throw new InvalidAnnotationException(string.Format("CursorPropertyName must be defined: {0}.{1}", method.DeclaringType.FullName, method.Name));
if (NewCursorTypeName == null)
throw new InvalidAnnotationException(string.Format("NewCursorType must be defined: {0}.{1}", method.DeclaringType.FullName, method.Name));
return base.CompileTimeValidate(method);
}
/// <summary>
/// Initialise the information required for this attribute
/// at runtime
/// </summary>
/// <param name="method"></param>
public override void RuntimeInitialize(MethodBase method)
{
base.RuntimeInitialize(method);
PropertyInfo pi = typeof(Cursors).GetProperty(NewCursorTypeName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
NewCursorType = (Cursor)pi.GetValue(null, null);
try
{
// If attribute associated with extension method use the type of the
// first parameter to associate the property with
if (method.IsDefined(typeof(ExtensionAttribute), false))
{
ParameterInfo paramInfo = method.GetParameters()[0];
Type type1 = paramInfo.ParameterType;
CursorPropertyInfo = type1.GetProperty(CursorPropertyName);
IsExtensionMethodAttribute = true;
}
else
CursorPropertyInfo = method.DeclaringType.GetProperty(CursorPropertyName);
}
catch (Exception ex)
{
throw new InvalidAnnotationException(string.Format("CursorPropertyName {2} not found in type: {0}.{1}\n{3}\n", method.DeclaringType.FullName, method.Name, CursorPropertyName, ex.GetType().FullName, ex.Message));
}
}
/// <summary>
/// On entry to a method set the cursor type to the required
/// type as specified in the attribute arguments
/// </summary>
/// <param name="args">The arguments to the method</param>
public override sealed void OnEntry(MethodExecutionArgs args)
{
CursorPropertyInfo.SetValue(GetInstance(args), NewCursorType, null);
}
/// <summary>
/// On method exit, regardless of success or failure reset
/// the form cursor to the default cursor type
/// </summary>
/// <param name="args">The arguments to the method</param>
public override sealed void OnExit(MethodExecutionArgs args)
{
CursorPropertyInfo.SetValue(GetInstance(args), Cursors.Default, null);
}
/// <summary>
/// Get the object instance that contains the Cursor property
/// depending on whether this attribute is attached to a method
/// within a class or an extension method
/// </summary>
/// <param name="args">The arguments to the method</param>
/// <returns>The instance object</returns>
private object GetInstance(MethodExecutionArgs args)
{
object instance = args.Instance;
if (IsExtensionMethodAttribute)
instance = args.Arguments[0];
return instance;
}
}