Change C# action/delegate target: hierarchical calls
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.
精彩评论