У меня есть метод расширения, созданный для дебатации действия делегировать функции. Предназначен для использования в обработчиках событий и еще много чего, которые испускают много событий, которые я хочу ограничить. < /P>
public static Action Debounce(this Action debounceDelegate, int delayMs = 500)
{
TArg? triggerArg = default;
Timer? triggerTimer = default;
return DebounceHandler;
void DebounceHandler(TArg arg)
{
triggerArg = arg;
if (triggerTimer is null)
triggerTimer = new(TriggerDelegate, null, delayMs, Timeout.Infinite);
else
triggerTimer.Change(delayMs, Timeout.Infinite);
}
void TriggerDelegate(object? _)
{
var arg = triggerArg;
var @delegate = debounceDelegate;
triggerArg = default;
triggerTimer!.Dispose();
triggerTimer = null;
@delegate.Invoke(arg);
}
}
< /code>
Это прекрасно работает для моего варианта использования, но я хотел обобщить это, чтобы работать для всех основных делегатов (по сути, все типы действий, потенциально все типы фанков). Технически кажется, что это должно быть простой, та же структура и использовать Delegate.dynamicinvoke (объект? Проблема заключается в создании обработчика, который такой же, как и исходный тип делегата, я не знаю, как его создать. < /P>
public static TDelegate Debounce(this TDelegate debounceDelegate, int delayMs = 500)
where TDelegate : Delegate
{
object?[]? triggerArgs = default;
Timer? triggerTimer = default;
return MagicConversion(DebounceHandler); // need this magic conversion function
void DebounceHandler(object?[]? args)
{
triggerArgs = args;
if (triggerTimer is null)
triggerTimer = new(TriggerDelegate, null, delayMs, Timeout.Infinite);
else
triggerTimer.Change(delayMs, Timeout.Infinite);
}
void TriggerDelegate(object? state)
{
var args = triggerArgs;
var @delegate = debounceDelegate;
triggerArgs = default;
triggerTimer!.Dispose();
triggerTimer = null;
@delegate.DynamicInvoke(args);
}
}
< /code>
private static TDelegate MagicConversion(Action @delegate)
where TDelegate : Delegate
{
// TODO: implement me
}
< /code>
I'm able to convert a function from arbitrary delegate to Delegate(object?[] args)
с использованием delegate.dynamicinvoke () . Существует ли доступный метод «обратного», который может преобразовать общего делегата обратно в конкретный делегат? Но давайте придерживаться общего случая.
У меня есть метод расширения, созданный для дебатации действия делегировать функции. Предназначен для использования в обработчиках событий и еще много чего, которые испускают много событий, которые я хочу ограничить. < /P> [code]public static Action Debounce(this Action debounceDelegate, int delayMs = 500) { TArg? triggerArg = default; Timer? triggerTimer = default; return DebounceHandler;
void DebounceHandler(TArg arg) { triggerArg = arg; if (triggerTimer is null) triggerTimer = new(TriggerDelegate, null, delayMs, Timeout.Infinite); else triggerTimer.Change(delayMs, Timeout.Infinite); } void TriggerDelegate(object? _) { var arg = triggerArg; var @delegate = debounceDelegate; triggerArg = default; triggerTimer!.Dispose(); triggerTimer = null; @delegate.Invoke(arg); } } < /code> Это прекрасно работает для моего варианта использования, но я хотел обобщить это, чтобы работать для всех основных делегатов (по сути, все типы действий, потенциально все типы фанков). Технически кажется, что это должно быть простой, та же структура и использовать Delegate.dynamicinvoke (объект? Проблема заключается в создании обработчика, который такой же, как и исходный тип делегата, я не знаю, как его создать. < /P> public static TDelegate Debounce(this TDelegate debounceDelegate, int delayMs = 500) where TDelegate : Delegate { object?[]? triggerArgs = default; Timer? triggerTimer = default; return MagicConversion(DebounceHandler); // need this magic conversion function
void DebounceHandler(object?[]? args) { triggerArgs = args; if (triggerTimer is null) triggerTimer = new(TriggerDelegate, null, delayMs, Timeout.Infinite); else triggerTimer.Change(delayMs, Timeout.Infinite); } void TriggerDelegate(object? state) { var args = triggerArgs; var @delegate = debounceDelegate; triggerArgs = default; triggerTimer!.Dispose(); triggerTimer = null; @delegate.DynamicInvoke(args); } } < /code> private static TDelegate MagicConversion(Action @delegate) where TDelegate : Delegate { // TODO: implement me } < /code> I'm able to convert a function from arbitrary delegate to Delegate(object?[] args)[/code] с использованием delegate.dynamicinvoke () . Существует ли доступный метод «обратного», который может преобразовать общего делегата обратно в конкретный делегат? Но давайте придерживаться общего случая.