在 C# 中使用反射添加和删除异步事件处理程序
Add and remove async event handlers using reflection in c#
我有以下实际有效的代码示例:
namespace DeviceLib
{
public interface IInstrument
{
event Action<InstrumentConnectionStatus> OnConnectionChanged;
event Action OnRemoteMeasureRequested;
}
public class InstrumentInstance
{
public delegate Task EventCompletedHandler(object sender, dynamic eventArgs);
public event EventCompletedHandler StatusChanged = async delegate { };
public event EventCompletedHandler RemoteMeasureRequested = async delegate { };
IInstrument Instrument;
public InstrumentInstance(string DriverName)
{
Instrument = DriverName switch
{
Instrument1.DRIVER => new Instrument1Driver(),
instrument2.DRIVER => new Instrument2Driver(),
_ => throw new NotSupportedException($"Driver {DriverName} not supported"),
};
}
public async Task<object> OnStatusChanged()
{
Instrument.OnConnectionChanged += async (InstrumentConnectionStatus status) =>
{
await StatusChanged(nameof(OnStatusChanged), status.ToString());
};
return null;
}
public async Task<object> OnRemoteMeasureRequested()
{
Instrument.OnRemoteMeasureRequested += async () =>
{
await RemoteMeasureRequested(nameof(OnRemoteMeasureRequested), null);
};
return null;
}
}
}
namespace DeviceConsumer
{
public class InstrumentService
{
static Type Type = typeof(DeviceLib.InstrumentInstance);
DeviceLib.InstrumentInstance InstrumentInstance;
static List<MethodInfo> AvailableEventHandlers = Type.GetMethods().Where(x => x.DeclaringType == Type && !x.IsSpecialName && x.Name.StartsWith("On")).ToList();
static List<EventInfo> AvailableEvents=Type.GetEvents().ToList();
public InstrumentService()
{
}
public async Task CreateInstrumentInstance(string driverName)
{
this.InstrumentInstance = new DeviceLib.InstrumentInstance(driverName);
// Invoking the methods that wrap the event handlers with reflection
foreach (MethodInfo eventHandler in AvailableEventHandlers)
await (Task<object>)eventHandler.Invoke(InstrumentInstance, new object[] { });
InstrumentInstance.StatusChanged += async(s,e) => await ProcessInstrumentEvent(s,e);
InstrumentInstance.RemoteMeasureRequested += async (s, e) => await ProcessInstrumentEvent(s, e);
}
private async Task ProcessInstrumentEvent(object sender, dynamic eventArgs)
{
await Task.Run(() =>
{
Console.Write($"Event {sender} Fired!");
});
}
}
现在我想将与事件关联的静态部分替换为 ProcessInstrumentEvent 方法:
InstrumentInstance.StatusChanged += async(s,e) => await ProcessInstrumentEvent(s,e);
InstrumentInstance.RemoteMeasureRequested += async (s, e) => await ProcessInstrumentEvent(s, e);
类似的东西:
foreach (EventInfo ev in AvailableEvents)
{
// EventHandler handler = async delegate (object s, dynamic e) { await ProcessInstrumentEvent(s, e); };
// EventHandler handler = new EventHandler(async (s, e) => await ProcessInstrumentEvent(s,e));
ev.AddEventHandler(InstrumentInstance, handler);
}
None 两种定义“处理程序”的方法都有效,我在这里失败了吗?我想我非常接近,这个实现的目标是动态添加(然后删除)在 class “InstrumentService” 中以方法“ProcessInstrumentEvent”为目标的处理程序,因此不使用 += 和 -= 运算符,所以我认为我可以使用反射方法“AddEventHandler”和“RemoveEventHandler”来实现这一点
这应该有效:
var obj = new InstrumentInstance("foo");
EventCompletedHandler handler = async (s, e) => await ProcessInstrumentEvent(s, e);
foreach (var evt in obj.GetType().GetEvents(BindingFlags.Public | BindingFlags.Instance))
{
if (evt.EventHandlerType == typeof(EventCompletedHandler))
{
Console.WriteLine($"Binding '{evt.Name}'");
evt.AddEventHandler(obj, handler);
}
}
它也应该在没有额外间接寻址的情况下工作:
EventCompletedHandler handler = ProcessInstrumentEvent;
我有以下实际有效的代码示例:
namespace DeviceLib
{
public interface IInstrument
{
event Action<InstrumentConnectionStatus> OnConnectionChanged;
event Action OnRemoteMeasureRequested;
}
public class InstrumentInstance
{
public delegate Task EventCompletedHandler(object sender, dynamic eventArgs);
public event EventCompletedHandler StatusChanged = async delegate { };
public event EventCompletedHandler RemoteMeasureRequested = async delegate { };
IInstrument Instrument;
public InstrumentInstance(string DriverName)
{
Instrument = DriverName switch
{
Instrument1.DRIVER => new Instrument1Driver(),
instrument2.DRIVER => new Instrument2Driver(),
_ => throw new NotSupportedException($"Driver {DriverName} not supported"),
};
}
public async Task<object> OnStatusChanged()
{
Instrument.OnConnectionChanged += async (InstrumentConnectionStatus status) =>
{
await StatusChanged(nameof(OnStatusChanged), status.ToString());
};
return null;
}
public async Task<object> OnRemoteMeasureRequested()
{
Instrument.OnRemoteMeasureRequested += async () =>
{
await RemoteMeasureRequested(nameof(OnRemoteMeasureRequested), null);
};
return null;
}
}
}
namespace DeviceConsumer
{
public class InstrumentService
{
static Type Type = typeof(DeviceLib.InstrumentInstance);
DeviceLib.InstrumentInstance InstrumentInstance;
static List<MethodInfo> AvailableEventHandlers = Type.GetMethods().Where(x => x.DeclaringType == Type && !x.IsSpecialName && x.Name.StartsWith("On")).ToList();
static List<EventInfo> AvailableEvents=Type.GetEvents().ToList();
public InstrumentService()
{
}
public async Task CreateInstrumentInstance(string driverName)
{
this.InstrumentInstance = new DeviceLib.InstrumentInstance(driverName);
// Invoking the methods that wrap the event handlers with reflection
foreach (MethodInfo eventHandler in AvailableEventHandlers)
await (Task<object>)eventHandler.Invoke(InstrumentInstance, new object[] { });
InstrumentInstance.StatusChanged += async(s,e) => await ProcessInstrumentEvent(s,e);
InstrumentInstance.RemoteMeasureRequested += async (s, e) => await ProcessInstrumentEvent(s, e);
}
private async Task ProcessInstrumentEvent(object sender, dynamic eventArgs)
{
await Task.Run(() =>
{
Console.Write($"Event {sender} Fired!");
});
}
}
现在我想将与事件关联的静态部分替换为 ProcessInstrumentEvent 方法:
InstrumentInstance.StatusChanged += async(s,e) => await ProcessInstrumentEvent(s,e);
InstrumentInstance.RemoteMeasureRequested += async (s, e) => await ProcessInstrumentEvent(s, e);
类似的东西:
foreach (EventInfo ev in AvailableEvents)
{
// EventHandler handler = async delegate (object s, dynamic e) { await ProcessInstrumentEvent(s, e); };
// EventHandler handler = new EventHandler(async (s, e) => await ProcessInstrumentEvent(s,e));
ev.AddEventHandler(InstrumentInstance, handler);
}
None 两种定义“处理程序”的方法都有效,我在这里失败了吗?我想我非常接近,这个实现的目标是动态添加(然后删除)在 class “InstrumentService” 中以方法“ProcessInstrumentEvent”为目标的处理程序,因此不使用 += 和 -= 运算符,所以我认为我可以使用反射方法“AddEventHandler”和“RemoveEventHandler”来实现这一点
这应该有效:
var obj = new InstrumentInstance("foo");
EventCompletedHandler handler = async (s, e) => await ProcessInstrumentEvent(s, e);
foreach (var evt in obj.GetType().GetEvents(BindingFlags.Public | BindingFlags.Instance))
{
if (evt.EventHandlerType == typeof(EventCompletedHandler))
{
Console.WriteLine($"Binding '{evt.Name}'");
evt.AddEventHandler(obj, handler);
}
}
它也应该在没有额外间接寻址的情况下工作:
EventCompletedHandler handler = ProcessInstrumentEvent;