开发者

Change C# action/delegate target: hierarchical calls

开发者 https://www.devze.com 2022-12-10 13:45 出处:网络
Suppose I have public IList<Entity> Children { get; set; } public NotifyChildren(Func<object, bool> action, object data)

Suppose I have

public IList<Entity> Children { get; set; }

public NotifyChildren(Func<object, bool> action, object data)
{
   foreach (var child in Children)
       if (action(data))
           /// <-- !!!! need action to work on child this time, not on the original target
           //child.NofifyChildren(action, data); <- this doesn't work because of the above requirement
           child.NotifyChild开发者_如何学JAVAren(action.ChangeTargetTo(child), data); // << pseudocode!
}

public void SomeChangeOccured()
{
   var changedChild;
   NotifyChildren(x => x.SomeHandler(), "somedata");
}

How do I change the target of the action? I'm OK to pass a delegate instead of action but its .Target is read-only, too. Currently I think doing

public NotifyChildren(Expression<Func<Entity, bool>> action, object data)
{
     // so that I can do method.Invoke(newtarget, new object[]{data});
     NotifyChildren(((MethodCallExpression)action).Method, data);
}

that is, switch from action to reflected method call... but it's a bit ugly, isn't it?

I have a feeling that the solution is very simple and I used to know it... just forgot.

Hm, one solution would be to have static delegate that accepts Entity as first parameter, but I wouldn't want to go this way.


What you're specifically asking for isn't possible. A delegate represents a statically bound method, whereas you're looking for something dynamic. To do that specifically you need reflection.

However, your code appears to be structured in the correct way to accomplish what you want, but the code doesn't look like it's being called correctly.

You define action as Func<Entity, bool>, but you pass in data (which is an object) rather than child (which is an Entity). It seems like you should actually declare it as Func<Entity, object, bool> and do it like this:

public IList<Entity> Children { get; set; }

public NotifyChildren(Func<Entity, object, bool> action, object data)
{
   foreach (var child in Children)
   {
       if (action(child, data))
       {
           child.NofifyChildren(action, data); 
       }
   }
}

public void SomeChangeOccured()
{
     NotifyChildren((x, data) => x.SomeHandler(data), "somedata");
}

public bool SomeHandler(object data)
{
     return true; // obviously need more robust logic
}


foreach (var child in Children)
   if (action(data))
       /// <-- !!!! need action to work on child this time, not on the original target
       child.NofifyChildren(action, data); 

WHY you call action in this loop? I think you can call it only once before foreach.

0

精彩评论

暂无评论...
验证码 换一张
取 消