public event EventHandler ConstructDesign;
public DataGridView dataGrid = new DataGridView();
public FooClass(Action action) {
ConstructDesign+=action;
dataGrid.DataBindingComplete+=ConstructDesign;
}
public void Launch() {
ConstructDesign(null, new EventArgs());
}
//IN A COMPLETELY DIFFERENT CLASS:
public void Main(string[] args) {
var launcher = new FooClass(Fire);
launcher.Launch();
}
public void Fire(object sender, EventHandlerArgs args...) {
Console.WriteLine("Fired");
//and after the first fire, action will be removed from the `ConstructDesign`.
}
所以基本上我在这里想要实现的是如何做到以下几点:
通过代码手动添加到Action
的{{1}},在触发后,它会将自己从事件处理程序ConstructDesign
中删除。任何想法?
答案 0 :(得分:1)
我不相信你可以阻止事件发生,但你可以阻止事件中的代码执行。这很简单,在类级别添加static bool
,将其初始化为true
,在第一次执行后将其设置为false
。将代码包装在if (firstExecution) {//actions I only want executed the first time the event fires}
答案 1 :(得分:1)
我不明白为什么你班上有活动,因为你没有在任何地方订阅它们。改为调用传递的操作:
Action _action;
public FooClass(Action action)
{
_action = action;
}
public void Launch()
{
if (_action == null)
return;
_action();
_action = null;
}
答案 2 :(得分:1)
我没有找到一个很好的方法来在第一次使用后取消订阅该事件。 (你当然可以使用反射密集的方法,但我怀疑如果重构改变了事件的名称,编译器会抱怨。)
这是一个仅使用委托的程序,因此编译器仍然可以很好地为您服务。它可能不像你需要的那么轻,但是因为我接受了我自己的启发的挑战,我想我会分享它。
MyEvent += SingleUseEventHandler<AssemblyLoadEventArgs, AssemblyLoadEventHandler>
.Create(This_MyEventOccurred);
这里定义了魔法:
public class SingleUseEventHandler<TArgs,THandler>
where TArgs : EventArgs
{
public static THandler Create(EventHandler<TArgs> handler)
{
var helper = new SingleUseEventHandler<TArgs, THandler>(handler);
EventHandler<TArgs> h = helper.InvokeIfFirstTime;
return (THandler)(object)Delegate.CreateDelegate(typeof(THandler), h.Target, h.Method);
}
public void InvokeIfFirstTime(object sender, TArgs args)
{
if (!raised)
{
raised = true;
handler(sender, args);
}
}
public SingleUseEventHandler(EventHandler<TArgs> handler)
{
this.handler = handler;
}
bool raised;
readonly EventHandler<TArgs> handler;
}
当然,C#不会推断出委托类型,因此你必须明确指定它。
如果事件的定义是EventHandler,您可以改为使用它:
MyEvent += SingleUseEventHandler<SomeEventArgs>.Create(SomeHandlerMethod);
public static class SingleUseEventHandler<TArgs>
where TArgs : EventArgs
{
public static EventHandler<TArgs> Create(EventHandler<TArgs> handler)
{
var helper = new SingleUseEventHandler<TArgs, EventHandler<TArgs>>(handler);
return helper.InvokeIfFirstTime;
}
}
这是一个示例程序:
class Program
{
static event AssemblyLoadEventHandler MyEvent;
static int callCount;
static void Main(string[] args)
{
MyEvent += SingleUseEventHandler<AssemblyLoadEventArgs, AssemblyLoadEventHandler>
.Create(Load);
foreach(var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine("Raising event for " + assembly.GetName().Name);
MyEvent(null, new AssemblyLoadEventArgs(assembly));
}
}
static void Load(object sender, AssemblyLoadEventArgs eventArgs)
{
Console.WriteLine(++callCount);
}
}
答案 3 :(得分:0)
只有拥有订阅者才会触发事件,所以你不能只通过-=
删除代理,或者我误解了你想做什么?
答案 4 :(得分:0)
public class FooEvents {
public event EventHandler ConstructDesign;
public DataGridView dataGrid = new DataGridView();
public FooEvents(Action action) {
ConstructDesign+=action;
dataGrid.DataBindingComplete+=ConstructDesign;
dataGrid.DataBindingComplete+=RemoveSubscribtion;
}
public void Launch() {
ConstructDesign(this, new EventArgs()); //passes FooEvent and fires.
}
private void RemoveSubscribtion(object sender, EventArgs args) {
dataGrid.DataBindingComplete-=ConstructDesign;
dataGrid.DataBindingComplete-=RemoveSubscribtion;
}
public Main {
public void Main(string[] args) {
var launcher = new FooClass(Fire);
launcher.Launch();
}
public void Fire(object sender, EventHandlerArgs args) {
Console.WriteLine("Fired");
}
}