[英]How to add an event handler exactly once, if it doesn't exists
I need to add and remove event handlers on my collection change: 我需要在我的集合更改中添加和删除事件处理程序:
public void SetStorageProviderFor<T>(Expression<Func<T, object>> expr, IStorageProvider sp) where T : class
{
MemberExpression me = (MemberExpression)expr.Body;
Set<T>().Local.CollectionChanged +=
(sender, args) =>
{
foreach (var item in args.NewItems)
{
// get entity's property on member expression and set its value
}
}
}
How can i remove some specific handler? 我该如何删除一些特定的处理程序? I don't think I should repeat all the same code but with "-=" mark...
我不认为我应该重复所有相同的代码,但用“ - =”标记...
I also tried to make the handler an Action
to store it in memory and let it be unassigned from CollectionChanged
at any time: 我还试图让处理程序成为一个
Action
来将它存储在内存中,并让它随时从CollectionChanged
中取消分配:
Action<object, NotifyCollectionChangedEventArgs> act = (sender, args) => { }
but CollectionChanged
cannot accept this Action as handler :( 但
CollectionChanged
无法接受此Action作为处理程序:(
Any help is appreciated. 任何帮助表示赞赏。
UPDATE UPDATE
My apologies, i shoud have posted more real code. 我道歉,我发布了更多真实的代码。 The problem is that my handler is using more parameters than only of
CollectionChanged
and needs also expr
and sp
of the SetStorageProviderFor
method. 问题是我的处理程序使用的参数多于
CollectionChanged
参数,还需要SetStorageProviderFor
方法的expr
和sp
。 In this case I can create named method as Tim S. advices but if i provide it with additional params then i'll not be able to assign it to Set<T>().Local.CollectionChanged
directly, will need anonymous lambda again ;( 在这种情况下,我可以创建命名方法作为Tim S.建议,但如果我提供额外的参数,那么我将无法将其分配给
Set<T>().Local.CollectionChanged
直接,将需要匿名lambda; (
I'd recommend that you keep something to match T
to your last handler, such as a dictionary. 我建议您保留一些东西以匹配
T
到您的上一个处理程序,例如字典。 I'm using a static
dictionary, but if an instance one is what's needed, (so that it's the combination of this type and T
, and not just statically T
, that won't get more than one handler attached) change it to that. 我正在使用一个
static
字典,但如果一个实例是需要的,(因此它是这种类型和T
的组合,而不仅仅是静态T
,它不会得到多个处理程序)将它改为。
In order to remove a handler from an event, you need to use -=
and it needs to match the delegate that was first added. 为了从事件中删除处理程序,您需要使用
-=
并且它需要匹配首次添加的委托。 It equates the delegates using, among other things, the instance of the object that is created. 它等同于代理使用创建的对象的实例等。 This would be difficult to recreate due to the complexity of your lambda (and the classes/methods that are generated from it), so it's easier to store the old value in a way you can refer back to.
由于lambda(以及从中生成的类/方法)的复杂性,这很难重新创建,因此以您可以引用的方式存储旧值更容易。
private static Dictionary<Type, NotifyCollectionChangedEventHandler> handlers =
new Dictionary<Type, NotifyCollectionChangedEventHandler>();
public void SetStorageProviderFor<T>(Expression<Func<T, object>> expr,
IStorageProvider sp) where T : class
{
var local = Set<T>().Local;
MemberExpression me = (MemberExpression)expr.Body;
NotifyCollectionChangedEventHandler existing;
if (handlers.TryGetValue(typeof(T), out existing))
{
local.CollectionChanged -= existing;
}
NotifyCollectionChangedEventHandler newHandler =
(sender, args) =>
{
foreach (var item in args.NewItems)
{
// get entity's property on member expression and set its value
// (uses expr and sp)
}
};
local.CollectionChanged += newHandler;
handlers[typeof(T)] = newHandler;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.