C# 在c中使用泛型和Func避免代码重复的最佳方法#

C# 在c中使用泛型和Func避免代码重复的最佳方法#,c#,generics,func,code-duplication,C#,Generics,Func,Code Duplication,我想知道使用泛型Func或任何其他方法避免重复某些代码结构的最佳方法是什么。 作为一个实际的例子,我需要调用20个不同的WCF方法,但我希望有更多的代码来处理异常 假设这是wcf代理 class ClassWithMethodsToCall // say wcf proxy { public Out1 GetOut1(In1 inParam) { return null; } // would have some spesific implementation

我想知道使用泛型Func或任何其他方法避免重复某些代码结构的最佳方法是什么。 作为一个实际的例子,我需要调用20个不同的WCF方法,但我希望有更多的代码来处理异常

假设这是wcf代理

 class ClassWithMethodsToCall // say wcf proxy
    {
        public Out1 GetOut1(In1 inParam) { return null; } // would have some spesific implementation 
        public Out2 GetOut2(In2 inParam) { return null; }
        public Out3 GetOut3(In3 inParam) { return null; }
    }

class Out1 { }  // some specific data structure
class In1 { }   // some specific data structure

class Out2 { }  // some specific data structure
class In2 { }   // some specific data structure

class Out3 { }  // some specific data structure
class In3 { }   // some specific data structure
我创建了下面的代码来处理一个错误

class CallerHelperWithCommonExceptionHandler
    {
        public Tout Call<Tout, Tin>(Tin parameters, Func<Tin,Tout> wcfMethodToCall)
        {
            try
            {
                return wcfMethodToCall(parameters);
            }
            catch (Exception ex)
            {
                // do what ever
                throw;
            }
        }
    }
类CallerHelpWithCommonExceptionHandler
{
公共Tout调用(Tin参数,Func wcfMethodToCall)
{
尝试
{
返回wcfMethodToCall(参数);
}
捕获(例外情况除外)
{
//做什么
投掷;
}
}
}
我用它:

var callerHelper = new CallerHelperWithCommonExceptionHandler();
            var theFunctionsToCall = new ClassWithMethodsToCall();

        var in1 = new In1(); // init as appropriate
        var ou1 = callerHelper.Call<Out1, In1>(in1, theFunctionsToCall.GetOut1);

        var in2 = new In2(); // init as appropriate
        var ou2 = callerHelper.Call<Out2, In2>(in2, theFunctionsToCall.GetOut2);

        // and so on
var callerHelper=new callerHelpWithCommonExceptionHandler();
var theFunctionsToCall=newclasswithmethodstocall();
var in1=新in1();//视情况而定
var ou1=callerHelper.Call(in1,functionstocall.GetOut1);
var in2=新in2();//视情况而定
var ou2=callerHelper.Call(in2,functionstocall.GetOut2);
//等等
有更好更优雅的方式吗?面向对象方式的替代方案,模板设计模式


谢谢,al

看起来您正在向类中添加代码来实现一个类(例如,记录异常),因此您可能需要使用

例如:

class Out1 { };  // some specific data structure
class In1 { }   // some specific data structure

class Out2 { }  // some specific data structure
class In2 { }   // some specific data structure

class Out3 { }  // some specific data structure
class In3 { }

internal interface IClassWithMethodsToCall
{
    Out1 GetOut1(In1 inParam);
    Out2 GetOut2(In2 inParam);
    Out3 GetOut3(In3 inParam);
}

class ClassWithMethodsToCallImpl: IClassWithMethodsToCall
{
    public Out1 GetOut1(In1 inParam) { return null; } // would have some spesific implementation 
    public Out2 GetOut2(In2 inParam) { return null; }
    public Out3 GetOut3(In3 inParam) { return null; }
}

class ClassWithMethodsToCall: IClassWithMethodsToCall
{
    private readonly ClassWithMethodsToCallImpl _impl;

    public ClassWithMethodsToCall(ClassWithMethodsToCallImpl impl)
    {
        _impl = impl;
    }

    public Out1 GetOut1(In1 inParam)
    {
        return tryFunc(() => _impl.GetOut1(inParam));
    }

    public Out2 GetOut2(In2 inParam)
    {
        return tryFunc(() => _impl.GetOut2(inParam));
    }

    public Out3 GetOut3(In3 inParam)
    {
        return tryFunc(() => _impl.GetOut3(inParam));
    }

    private static T tryFunc<T>(Func<T> func)
    {
        try
        {
            return func();
        }

        catch (Exception exception)
        {
            // Do something with exception
            throw;
        }
    }
}
class Out1{};//一些特定的数据结构
类{}//某些特定的数据结构
类Out2{}//某些特定的数据结构
类In2{}//某些特定的数据结构
类Out3{}//某些特定的数据结构
类In3{}
内部接口IClassWithMethodsToCall
{
Out1 GetOut1(In1 inParam);
Out2 GetOut2(In2 inParam);
Out3 GetOut3(In3 inParam);
}
类ClassWithMethodsToCallImpl:IClassWithMethodsToCall
{
public Out1 GetOut1(In1 inParam){return null;}//将有一些特殊的实现
public Out2 GetOut2(In2 inParam){return null;}
public Out3 GetOut3(In3 inParam){return null;}
}
类ClassWithMethodsToCall:IClassWithMethodsToCall
{
方法为CallImpl的私有只读类;
公共类WithMethodsToCall(类WithMethodsToCallImpl)
{
_impl=impl;
}
公共输出1输出1(输入1参数)
{
返回tryFunc(()=>_impl.GetOut1(inParam));
}
公共出口2出口2(In2输入参数)
{
返回tryFunc(()=>_impl.GetOut2(inParam));
}
公共出口3出口3(In3 inParam)
{
返回tryFunc(()=>_impl.GetOut3(inParam));
}
专用静态T tryFunc(Func Func)
{
尝试
{
返回func();
}
捕获(异常)
{
//例外地做某事
投掷;
}
}
}
客户端代码只会使用
IClassWithMethodsToCall
,您可能会在某个地方使用工厂方法创建
ClassWithMethodsToCallImpl
,并使用它创建
ClassWithMethodsToCall
,并将
ClassWithMethodsToCall
作为
IClassWithMethodsToCall
返回

或者(可能更好)使用。这需要更多的投资,可能还需要使用第三方库来支持,但从长远来看,这可能是一条路


我注意到您正在使用WCF代理。因为它使用MarshalByRefObject,所以您可以利用它来实现AOP

这根本不是重复。你的class
ClassWithMethodsToCall
看起来很适合我。您的
CallerHealthCommonExceptionHandler
使情况变得更糟。同意,看起来更糟。您正在寻找的可能是面向方面的编程短AOP这里是一个示例,没有CallerHealthCommonExceptionHandler,我必须对ClassWithMethodsToCall的每个metod调用重复try-catch。如果我有20个方法,我会为每个方法重复相同的错误处理代码块。而据我所知,AOP更具体于异常、日志记录等常见操作。我正在寻找适合任何常见代码块的东西,例如“1.解决方案:”似乎与我的类似您认为如何?@user241829是的,这与我展示的
private static T tryFunc(Func Func)
基本相同-您可以使用这种方法通过将重试放入
tryFunc()中来实现重试逻辑
@user241829 AOP不仅限于日志记录/异常处理,还可以实现缓存、事务处理等功能。拦截对objects方法的调用所需的一切。因此,在AOP中也可以使用重试逻辑