如果您使用相同的订阅订阅.net事件,那么您订阅的方法将与订阅的次数相同。如果您只取消订阅一次,那么它将只是一个减去电话。这意味着您必须取消订阅与订阅相同的时间,否则您将随时了解情况。有时你不想这样做。
为了防止事件处理程序被挂钩两次,我们可以实现如下事件。
private EventHandler foo;
public event EventHandler Foo
{
add
{
if( foo == null || !foo.GetInvocationList().Contains(value) )
{
foo += value;
}
}
remove
{
foo -= value;
}
}
现在我想实现Postsharp EventInterceptionAspect以使此解决方案通用,这样我就可以在每个事件上应用PreventEventHookedTwiceAttribute
来节省大量代码。但我无法弄清楚如何检查以下条件的第二部分。我的意思是foo.GetInvocationList()。包含(值)。我的PreventEventHookedTwiceAttribute看起来如下。
[Serializable]
public class PreventEventHookedTwiceAttribute: EventInterceptionAspect
{
public override void OnAddHandler(EventInterceptionArgs args)
{
if(args.Event == null || secondConditionRequired) // secondConditionRequired means it is required.
{
args.ProceedAddHandler();
}
}
}
我不需要覆盖OnRemoveHandler,因为默认功能就足够了。
答案 0 :(得分:2)
这个类可以解决这个问题。
[Serializable]
public class PreventEventHookedTwiceAttribute: EventInterceptionAspect
{
private readonly object _lockObject = new object();
readonly List<Delegate> _delegates = new List<Delegate>();
public override void OnAddHandler(EventInterceptionArgs args)
{
lock(_lockObject)
{
if(!_delegates.Contains(args.Handler))
{
_delegates.Add(args.Handler);
args.ProceedAddHandler();
}
}
}
public override void OnRemoveHandler(EventInterceptionArgs args)
{
lock(_lockObject)
{
if(_delegates.Contains(args.Handler))
{
_delegates.Remove(args.Handler);
args.ProceedRemoveHandler();
}
}
}
}
示例用于显示差异的用法如下所示。
class Program
{
private static readonly object _lockObject = new object();
private static int _counter = 1;
[PreventEventHookedTwice]
public static event Action<string> GoodEvent;
public static event Action<string> BadEvent;
public static void Handler (string message)
{
lock(_lockObject)
{
Console.WriteLine(_counter +": "+ message);
_counter++;
}
}
static void Main(string[] args)
{
GoodEvent += Handler;
GoodEvent += Handler;
GoodEvent += Handler;
GoodEvent += Handler;
GoodEvent += Handler;
Console.WriteLine("Firing Good Event. Good Event is subscribed 5 times from the same Handler.");
GoodEvent("Good Event is Invoked.");
_counter = 1;
BadEvent += Handler;
BadEvent += Handler;
BadEvent += Handler;
BadEvent += Handler;
BadEvent += Handler;
Console.WriteLine("Firing Bad Event. Bad Event is subscribed 5 times from the same Handler.");
BadEvent("Bad Event is Invoked.");
_counter = 1;
GoodEvent -= Handler;
Console.WriteLine("GoodEvent is unsubscribed just once. Now fire the Event");
if(GoodEvent!= null)
{
GoodEvent("Good Event Fired");
}
Console.WriteLine("Event is not received to Handler.");
BadEvent -= Handler;
Console.WriteLine("BadEvent is unsubscribed just once. Now fire the Event");
BadEvent("Good Event Fired");
Console.WriteLine("Event is fired 4 times. If u subscribe good event 5 times then u have to unscribe it for 5 times, otherwise u will be keep informed.");
Console.ReadLine();
}
}
Postsharp Rocks。