Предположим, что
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.NotifyChildren(action.ChangeTargetTo(child), data); // << pseudocode!
}
public void SomeChangeOccured()
{
var changedChild;
NotifyChildren(x => x.SomeHandler(), "somedata");
}
Как изменить цель действия? Я в порядке, чтобы передать делегат вместо действия, но его .Target также доступен только для чтения. В настоящее время я думаю, что делать
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);
}
то есть перейти от действия к отраженному вызову метода... но он бит уродливый, не так ли?
У меня такое ощущение, что решение очень простое, и я его знал... просто забыл.
Hm, одно решение должно состоять в том, чтобы иметь статический делегат, который принимает Entity в качестве первого параметра, но я бы не хотел идти этим путем.
То, что вы конкретно просите, невозможно. Делегат представляет собой статически связанный метод, тогда как вы ищете что-то динамическое. Для этого вам нужно отразить.
Тем не менее, ваш код, похоже, структурирован правильно, чтобы выполнить то, что вы хотите, но код выглядит не так, как будто его правильно называют.
Вы определяете action
как Func<Entity, bool>
, но вы передаете data
(который является object
), а не child
(который является Entity
). Похоже, вы должны объявить его как Func<Entity, object, bool>
и сделать это следующим образом:
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
}
SomeHandler
если вы не возражаете получить его MethodInfo
с отражением.
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);
ПОЧЕМУ вы вызываете действие в этом цикле? Я думаю, вы можете назвать это только один раз перед тем, как отправиться.