Как создать универсальный метод-обертку, который возвращает результат обернутого метода, если он есть? - PullRequest
1 голос
/ 11 июля 2019

Я пытаюсь создать метод, который принимает другой метод и возвращает значение, которое возвращает внутренний метод, если этот внутренний метод не является пустым.Я хотел бы сделать это, не делая различий между Func<> и Action<>.

По сути, я хочу, чтобы обернутый метод вел себя точно так же, как распакованный метод, плюс некоторая функциональность, предоставляемая оберткой.Цель достаточно проста, но мне сложно обернуться вокруг реализации.

public int ReturnsInteger() {
    Console.WriteLine("I return 42");
    return 42;
}

public static T WrapperMethod(Func<T> someMethod) {
    Console.WriteLine("Wrap start");
    var result = someMethod();
    Console.WriteLine("Wrap end");
    return result;
}

private static void Main() {
    var X = WrapperMethod(()=>ReturnsInt());
    Console.WriteLine("X = " + X);
    // Wrap start
    // I return 42
    // Wrap end
    // X = 42
}
public void ReturnsNothing() {
    Console.WriteLine("I return nothing");
    return;
}

public static T WrapperMethod(Action someMethod) {
    Console.WriteLine("Wrap start");
    someMethod();
    Console.WriteLine("Wrap end");
}

private static void Main() {
    WrapperMethod(()=>ReturnsNothing());
    // Wrap start
    // I return nothing
    // Wrap end
}

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Я бы попытался убрать фундаментальную языковую разницу в методе возврата void, фактически дав методу что-то для возврата.

Реализуя тип Unit, это всего лишь одно значение struct, тогда вы можете преобразовать Action в Func<Unit>.По сути, это просто использование шаблона адаптера.

Теперь вы имеете дело только с одним видом делегата в форме Func<T>.Затем вы можете поместить всю тяжелую работу в этот единственный Wrapper метод.

Попробуйте это:

void Main()
{
    var result = Wrapper(DoSomething);
}

private void DoSomething()
{
    Console.WriteLine("Test.");
}

T Wrapper<T>(Func<T> func)
{
    Console.WriteLine("Wrap start");
    var result = func();
    Console.WriteLine("Wrap end");
    return result;
}

Unit Wrapper(Action action)
{
    return Wrapper(() => { action(); return Unit.Default; });
}

/// <summary>
/// Represents a type with a single value. This type is often used to denote the successful completion of a void-returning method (C#) or a Sub procedure (Visual Basic).
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential, Size = 1)]
public struct Unit : IEquatable<Unit>
{
    public static Unit Default => default(Unit);
    public bool Equals(Unit other) => true;
    public override bool Equals(object obj) => obj is Unit;
    public override int GetHashCode() => 0;
    public override string ToString() => "()";
    public static bool operator ==(Unit first, Unit second) => true;
    public static bool operator !=(Unit first, Unit second) => false;
}
0 голосов
/ 11 июля 2019

Как отмечалось выше, я не совсем понимаю формулировку вашего вопроса.Тем не менее, базовый сценарий кажется простым: вы хотите в общих чертах украсить поведение неизвестных методов, обрабатывая как методы, которые возвращают значения, так и методы, которые этого не делают.

Всякий раз, когда я сталкиваюсь с этим типом сценария, я обращаюсь к немунаписав один метод-обертку с возвращаемым типом void, а затем адаптируя через лямбду второй метод-обертку.Например:

T Wrapper<T>(Func<T> func)
{
    T result = default(T);
    Wrapper(() => { result = func(); });
    return result;
}

void Wrapper(Action action)
{
    Console.WriteLine("Wrap start");
    action();
    Console.WriteLine("Wrap end");
}

Таким образом, мне нужно написать логику оболочки только один раз.В версии Func<T> есть некоторые издержки, связанные с созданием нового экземпляра делегата и захватом локальной переменной, но, по крайней мере, когда мне приходилось делать подобные вещи, логика обертки и обернутая логика достаточно сложны, чтобы накладные расходылямбда несущественна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...