我在C#中有以下行:
_timer.ElapsedTick += _somefunction1;
_timer.ElapsedTick += _somefunction2;
_timer.ElapsedTick += _somefunction3;
如何在不指定_somefunction的情况下调用订阅_timer.ElapsedTick的所有方法?沿着这条伪线的某个地方
invoke(_timer.ElapsedTick);
非常感谢您的帮助。
更新
@ M.Babcock的例子正在运作。 FireEvent方法具有魔力。谢谢。
class InvokeFromMe
{
public event EventHandler RaiseMe;
}
class MainClass
{
public MainClass()
{
InvokeFromMe fromMe = new InvokeFromMe();
fromMe.RaiseMe += fromMe_RaiseMe;
fromMe.RaiseMe += fromMe_RaiseMe1;
FireEvent(fromMe, "RaiseMe", null, EventArgs.Empty);
//works
System.Timers.Timer _timer = new System.Timers.Timer();
_timer.Elapsed += _timer_Elapsed;
FireEvent(_timer, "onIntervalElapsed", null, null);
//throws exception
}
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("_timer_Elapsed raised");
}
private void fromMe_RaiseMe(object sender, EventArgs e)
{
Console.WriteLine("Event Handler 0 Raised");
}
private void fromMe_RaiseMe1(object sender, EventArgs e)
{
Console.WriteLine("Event Handler 1 Raised");
}
public void FireEvent(object onMe, string invokeMe, params object[] eventParams)
{
MulticastDelegate eventDelagate =
(MulticastDelegate)onMe.GetType().GetField(invokeMe,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(onMe);
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, eventParams);
}
}
}
class Program
{
static void Main(string[] args)
{
MainClass m = new MainClass();
}
}
答案 0 :(得分:20)
可以使用传统的C#完成吗?不(as previously stated)。但使用反射是可能的。以下是一些基于this MSDN forum thread答案的测试代码:
class InvokeFromMe
{
public event EventHandler RaiseMe;
}
class Program
{
static void Main(string[] args)
{
var fromMe = new InvokeFromMe();
fromMe.RaiseMe += fromMe_RaiseMe;
fromMe.RaiseMe += fromMe_RaiseMe1;
fromMe.RaiseMe += fromMe_RaiseMe2;
FireEvent(fromMe, "RaiseMe", null, EventArgs.Empty);
}
static void fromMe_RaiseMe(object sender, EventArgs e)
{
Console.WriteLine("Event Handler 0 Raised");
}
static void fromMe_RaiseMe1(object sender, EventArgs e)
{
Console.WriteLine("Event Handler 1 Raised");
}
static void fromMe_RaiseMe2(object sender, EventArgs e)
{
Console.WriteLine("Event Handler 2 Raised");
}
public static void FireEvent(object onMe, string invokeMe, params object[] eventParams)
{
MulticastDelegate eventDelagate =
(MulticastDelegate)onMe.GetType().GetField(invokeMe,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(onMe);
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, eventParams);
}
}
}
<强>更新强>
我不熟悉System.Timer.Timer
类,所以我不确定与我提供的示例有什么不同。你也许可以尝试类似的东西:
public static void FirePublicEvent(object onMe, string invokeMe, params object[] eventParams)
{
MulticastDelegate eventDelagate =
(MulticastDelegate)onMe.GetType().GetField(invokeMe,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public).GetValue(onMe);
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, eventParams);
}
}
答案 1 :(得分:18)
您无法调用由其他类型拥有的事件。只能从声明它的类内部调用事件。
答案 2 :(得分:2)
你可以创建一个运行它们的函数:
public void RunAllFuncs()
{
_somefunction1();
_somefunction2();
_somefunction3();
}
答案 3 :(得分:2)
这是一个解决方法,你不能遍历Elapsed事件。但要调用它们,让计时器完成工作。 System.Timer的此代码,不确定您使用的是哪个计时器。
假定计时器已启用:
int interval = timer.Interval;
ElapsedEventHandler handler = null;
handler = (s,e) =>
{
timer.Interval = interval; // put interval back to original value
timer.Elapsed -= handler;
};
timer.Elapsed += handler;
timer.Interval = 1; // 1 millisecond, pretty much going to fire right now (as soon as you let it)
这样的事情将触发事件,但您的原始间隔将重新启动。如果你想保留原始的刻度模式,你可能需要在那里做一些数学运算。
答案 4 :(得分:1)
我认为您可能需要使用InvokeMember:
public void GetMethod(string methodName){
var args = new Object[] { [INSERT ARGS IF NECESSARY--SET TO NULL OTHERWISE] };
try
{
var t = new [INSERT NAME OF CLASS THAT CONTAINS YOUR METHOD]();
Type typeInfo = t.GetType();
var result = typeInfo.InvokeMember(methodName, BindingFlags.InvokeMethod, null, t, args);
return result;
}
catch (Exception ex)
{
return ex;
}
}
然后这样称呼:
_timer.ElapsedTick += GetMethod("[INSERT METHOD NAME AS STRING]");
请务必加入以下内容:
using System.Reflection;
祝你好运!
答案 5 :(得分:0)
基于上面的M.Babcock's answer,有一些轻微的反射方法更新。
将GetField
替换为GetTypeInfo
和GetDeclaredField
,将dlg.Method
替换为dlg.GetMethodInfo
。
using System.Reflection;
...
public static void FireEvent(this object onMe, string invokeMe, params object[] eventParams)
{
TypeInfo typeInfo = onMe.GetType().GetTypeInfo();
FieldInfo fieldInfo = typeInfo.GetDeclaredField(invokeMe);
MulticastDelegate eventDelagate = (MulticastDelegate)fieldInfo.GetValue(onMe);
Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.GetMethodInfo().Invoke(dlg.Target, eventParams);
}
}
答案 6 :(得分:0)
我最终在这里搜索如何简单地启动事件,没有任何自定义args或任何东西。我知道OP问题不同!但我想分享,我希望它可以帮助别人。
不简化版本:
var Handler = EventNameHere;
if (Handler != null)
{
Handler(this, EventArgs.Empty);
}
简化版本:
EventNameHere?.Invoke(this, EventArgs.Empty);
答案 7 :(得分:-1)
根据ElapsedTick
事件的签名,您可以通过在声明它的类中调用它来触发事件。例如:
ElapsedTick(this, new EventArgs());
答案 8 :(得分:-1)
您只能从声明它的类中调用事件。如果您编写了计时器类,则可以这样调用它:
this.ElapsedTick(this, eventArgs);
在计时器类之外,您可以执行以下操作以获得类似的行为:
delegate void delegateSample(object sender, EventArgs e);
delegateSample d;
d += new delegateSample(_somefunction1);
d += new delegateSample(_somefunction2);
d(this, EventArgs.Empty);
delegateSample实际上应该是ElapsedTick事件的类型,而不是声明另一个委托类型。我只是不知道那个代表的名字。只需确保添加ElapsedTick事件和您声明的委托变量的每个函数,然后您可以从Timer类之外的委托中调用它们。