PostSharp का उपयोग कर संकलन चरण में संकलित असेंबली को समायोजित करना संभव है। यह आपको क्रॉस-कटिंग चिंताओं को हल करने, कोड में 'पहलुओं' लागू करने की अनुमति देता है।
हालांकि शून्य जांच या खाली प्रतिनिधि प्रारंभिकता बहुत मामूली समस्या हो सकती है, मैंने एक पहलू लिखा जो असेंबली में सभी घटनाओं में एक खाली प्रतिनिधि जोड़कर इसे हल करता है।
यह उपयोग काफी आसान है:
[assembly: InitializeEventHandlers(AttributeTargetTypes = "Main.*")]
namespace Main
{
...
}
मैं discussed the aspect in detail on my blog। मामले में आप PostSharp है, यहाँ पहलू है:
/// <summary>
/// Aspect which when applied on an assembly or class, initializes all the event handlers (<see cref="MulticastDelegate" />) members
/// in the class(es) with empty delegates to prevent <see cref="NullReferenceException" />'s.
/// </summary>
/// <author>Steven Jeuris</author>
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Event)]
[MulticastAttributeUsage(MulticastTargets.Event, AllowMultiple = false)]
[AspectTypeDependency(AspectDependencyAction.Commute, typeof(InitializeEventHandlersAttribute))]
[Serializable]
public class InitializeEventHandlersAttribute : EventLevelAspect
{
[NonSerialized]
Action<object> _addEmptyEventHandler;
[OnMethodEntryAdvice, MethodPointcut("SelectConstructors")]
public void OnConstructorEntry(MethodExecutionArgs args)
{
_addEmptyEventHandler(args.Instance);
}
// ReSharper disable UnusedMember.Local
IEnumerable<ConstructorInfo> SelectConstructors(EventInfo target)
{
return target.DeclaringType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
// ReSharper restore UnusedMember.Local
public override void RuntimeInitialize(EventInfo eventInfo)
{
base.RuntimeInitialize(eventInfo);
// Construct a suitable empty event handler.
MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType(eventInfo.EventHandlerType);
ParameterExpression[] parameters = delegateInfo.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
Delegate emptyDelegate
= Expression.Lambda(eventInfo.EventHandlerType, Expression.Empty(), "EmptyDelegate", true, parameters).Compile();
// Create a delegate which adds the empty handler to an instance.
_addEmptyEventHandler = instance => eventInfo.AddEventHandler(instance, emptyDelegate);
}
}
... और सहायक विधि का उपयोग करता है:
/// <summary>
/// The name of the Invoke method of a Delegate.
/// </summary>
const string InvokeMethod = "Invoke";
/// <summary>
/// Get method info for a specified delegate type.
/// </summary>
/// <param name = "delegateType">The delegate type to get info for.</param>
/// <returns>The method info for the given delegate type.</returns>
public static MethodInfo MethodInfoFromDelegateType(Type delegateType)
{
Contract.Requires(delegateType.IsSubclassOf(typeof(MulticastDelegate)), "Given type should be a delegate.");
return delegateType.GetMethod(InvokeMethod);
}
स्रोत
2012-03-26 00:20:30
देखें: http://www.dailycoding.com/Posts/avoiding_event__null_check.aspx विस्तारित स्पष्टीकरण के लिए। –