簡體   English   中英

C#方法,無論輸入/返回類型如何,都將另一種方法作為參數

[英]C# Method which takes another method as an argument regardless of input/return type

如果標題不清楚,我很抱歉。 基本上,我想通過將許多重復的錯誤處理移到一個位置來干燥我的代碼。

我正在調用幾種方法,所有方法都會引發類似的錯誤。 每個參數采用不同的參數,並返回不同的類型。 我希望能夠執行以下操作:

public class MyClass {
    public static ErrorWrapper<Void> Method1(string s1, string s2) {
        return Wrapper<Void>(System.Method1, s1, s2);
    }

    public static ErrorWrapper<string> Method2(string s) {
        return Wrapper<string>(System.Method2, s);
    }

    public static ErrorWrapper<MyOtherClass> Method3(string s, int i) {
        return Wrapper<MyOtherClass>(System.Method3, s, i)
    }

    private static ErrorWrapper<T> Wrapper<T>(Func f, /*parameters?*/) {
        try {
            return f(parameters);
        } catch {
            // Handle exceptions
        }
}

之所以需要這樣做,是因為我編寫的語言綁定沒有異常處理,因此使用錯誤包裝類是安全地調用標准庫方法的唯一方法。

除非我在這里想念什么-

private static ErrorWrapper<T> Wrapper<T>(Func<T> f) 
{
    // implementation
}

用法:

return Wrapper<string>(() => System.Method2(s));

return Wrapper<MyOtherClass>(() => System.Method3(s, I));

這是基於對您正在嘗試的理解而提出的建議。 不幸的是,在調用常規Delegate時,必須使用慢速的DynamicInvoke才能在運行時檢查類型。 您不能將void用作泛型的類型參數,因此我創建了一個我專門處理的MyVoid類。

我更新了答案,以反映System.Method是實際方法,而不是靜態字段,因此在傳遞給Wrapper<>時必須將其Wrapper<>轉換-C#無法將方法轉換為一般的Delegate

我還添加了類型安全的版本,但是需要創建許多樣板方法來處理參數數量,但是它確實消除了很多強制轉換並且可以靜態調用委托,這應該更高效。

我不小心讓Method3最初使用了兩個字符串參數,並且非類型安全版本在運行時調用之前沒有錯誤。 類型安全版本在編譯時發現了錯誤。

public class MyVoid { }

public class ErrorWrapper<T> {
    public T Result;
    public bool ValidResult;
    public Exception Exception;

    public ErrorWrapper(T res) {
        ValidResult = true;
        Result = res;
    }

    public ErrorWrapper(Exception e) {
        Exception = e;
        ValidResult = false;
    }

    public ErrorWrapper() { //  void
        ValidResult = true;
    }
}

public class MyClass {
    public static ErrorWrapper<MyVoid> Method1(string s1, string s2) => Wrapper<MyVoid>((Action<string, string>)System.Method1, s1, s2);
    public static ErrorWrapper<string> Method2(string s) => Wrapper<string>((Func<string, string>)System.Method2, s);
    public static ErrorWrapper<MyOtherClass> Method3(string s, int i) => Wrapper<MyOtherClass>((Func<string, int, MyOtherClass>)System.Method3, s, i);

    private static ErrorWrapper<T> Wrapper<T>(Delegate f, params object[] p) {
        try {
            switch (default(T)) {
                case MyVoid _:
                    f.DynamicInvoke(p);
                    return new ErrorWrapper<T>();
                default:
                    return new ErrorWrapper<T>((T)f.DynamicInvoke(p));
            }
        }
        catch (Exception e) {
            // Handle exceptions
            return new ErrorWrapper<T>(e);
        }
    }
}

public static class ErrorWrapper {
    public static ErrorWrapper<T> New<T>(T res) => new ErrorWrapper<T>(res);
}

public class MyTypeSafeClass {
    public static ErrorWrapper<MyVoid> Method1(string s1, string s2) => WrapperAction(System.Method1, s1, s2);
    public static ErrorWrapper<string> Method2(string s) => WrapperFunc(System.Method2, s);
    public static ErrorWrapper<MyOtherClass> Method3(string s, int i) => WrapperFunc(System.Method3, s, i);

    private static ErrorWrapper<MyVoid> WrapperAction<T1, T2>(Action<T1, T2> f, T1 p1, T2 p2) {
        try {
            f(p1, p2);
            return ErrorWrapper.New(default(MyVoid));
        }
        catch (Exception e) {
            // Handle exceptions
            return new ErrorWrapper<MyVoid>(e);
        }
    }

    private static ErrorWrapper<TRes> WrapperFunc<T1, TRes>(Func<T1, TRes> f, T1 p1) {
        try {
            return ErrorWrapper.New(f(p1));
        }
        catch (Exception e) {
            // Handle exceptions
            return new ErrorWrapper<TRes>(e);
        }
    }

    private static ErrorWrapper<TRes> WrapperFunc<T1, T2, TRes>(Func<T1, T2, TRes> f, T1 p1, T2 p2) {
        try {
            return ErrorWrapper.New(f(p1, p2));
        }
        catch (Exception e) {
            // Handle exceptions
            return new ErrorWrapper<TRes>(e);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM