(我不是100%肯定我明白你要什么,从示例钩子上生成的事件处理程序,但这里是我所知道的用于创建的最简单的方法一个事件处理程序)
取决于您的平台和信任级别。最灵活的方法是使用Emit
生成方法(请参阅here)。
但是,我发现一个相对容易使用和很好的替代方法来生成Linq表达式(这里是namespace help)。
的想法很简单:
使用各种表达派生类,你可以在命名空间中看到界定什么回调做。在这种情况下,您想要生成一个在ei
实例上调用.RemoveEventHandler
(我猜测)的东西(具体来说,您将使用ConstantExpression创建一个对您的ei
变量和您的回调参数的引用以及一个MethodCallExpression来创建对方法RemoveDataHandler
)。
一旦创建,它你需要什么,你需要创建一个委托(波长)出它的表达(见here)
差不多完成了。您仍然需要通过您从上一步骤(see here)
编辑得到调用对象的.Compile
编译拉姆达,你做的:这是一个动态生成的代表,消除自身的Windows控制台的例子。请注意,WP7 Linq表达式支持比.NET 4.0更有限,因此您需要对其进行调整(使帮助器方法可以完成一些工作,并从表达式中调用它们而不是我所做的)。
Edit2:BTW:lambda可以移除它自己的机制是创建另一个lambda返回一个局部变量。创建lambda后,将其保存到本地变量并运行代码(我不确定这是否会在没有次级lambda的情况下工作)
Edit3:否 - 您必须使用委托技巧,否则,常量得到“冻结”并且不会按照您希望的那样更新。所以代码是可行的。
public class MyEventArgs : EventArgs
{
}
public class EventContainer
{
public event EventHandler<MyEventArgs> MyEvent;
public void Fire()
{
Console.WriteLine("Firing");
if (MyEvent != null)
{
MyEvent(this, new MyEventArgs());
}
Console.WriteLine("Fired");
}
}
class Program
{
static void Main(string[] args)
{
EventContainer container = new EventContainer();
var adder = container.GetType().GetMethod("add_MyEvent");
var remover = container.GetType().GetMethod("remove_MyEvent");
object self = null;
Func<object> getSelf =() => self;
var block = Expression.Block(
// Call something to output to console.
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("Event called")),
// Now call the remove_Event method.
Expression.Call(
Expression.Constant(container), // passing the container as "this"
remover, // And the remover as the method info
Expression.Convert(// we need to cast the result of getSelf to the correct type to pass as an argument
Expression.Invoke(// For the parameter (what to convert), we need to call getSelf
Expression.Constant(getSelf)), // So this is a ref to getSelf
adder.GetParameters()[0].ParameterType) // finally, say what to convert to.
)
);
// Create a lambda of the correct type.
var lambda = Expression.Lambda(
adder.GetParameters()[0].ParameterType,
block,
Expression.Parameter(typeof(object)),
Expression.Parameter(typeof(MyEventArgs)));
var del = lambda.Compile();
// Make sure "self" knows what the delegate is (so our generated code can remove it)
self = del;
// Add the event.
adder.Invoke(container, new object[] { del });
// Fire once - see that delegate is being called.
container.Fire();
// Fire twice - see that the delegate was removed.
container.Fire();
}
}
感谢您的提示,它非常有用。可悲的是,我不能投票赞成由于缺乏声誉造成的答复。 还是我的问题没有完全解决。为了说清楚,我试图达到的目标,我将重新解释我对该方法的解释。该方法应该将由参数'Callback'定义的'Delegate'作为事件处理程序添加到事件中,由对象'DataContext'的参数'name'命名。在此之后,它应该添加一个EventHandler到'DataContext'的同一个事件中,该事件同时删除'Callback'和它自己。 – Kevkong 2012-03-27 14:23:45
啊。为此,您要使用反射来查找名为“add_”+名称和“remove_”+名称的MethodInfo。这些将是添加和删除事件处理程序的方法。 – 2012-03-27 15:51:20
请参阅我在这里的其他答案。正如我所说,只有一步失踪。我已经使用反射来添加一个事件处理程序,它将删除回调,但我仍然希望创建的方法从事件中删除自己,你现在是什么意思?在正常的代码中,它看起来像这样: Object.CallCompleted + = CallCompleted; Object.CallCompleted + = RemoveHandler; void RemoveHandler(object sender,CompletedEventArgs eA) Object.CallCompleted - = CallCompleted; Object.CallCompleted - = RemoveHandler; } – Kevkong 2012-03-27 21:09:47