跨通用函数隔离通用代码

时间:2019-01-04 10:51:53

标签: c# architecture

我在课堂上有两个职能。唯一的区别是函数的参数(一个带有X的Func,另一个带有Y的Func)以及标有星号的行。

是否有任何方法可以用星号分隔这两行或具有一个通用功能,或者重写这些功能以使try,catch块和最后几个语句仅被写入一次?

这里的目标是最大程度地减少代码重复。

Prod

2 个答案:

答案 0 :(得分:1)

创建接受管理器和功能的通用方法

    public T Do<T, TManager>(TManager manager, Func<TManager, T> something)
    {
        try
        {
            if (manager != null) return something(manager);
            LoggingHandler.LogWarning(LogTitle, $"manager ({this}) is null.");
        }
        catch (MyException exp)
        {
            ExceptionHandler.HandleRecoverableException(exp, LogTitle,
                $"query on manager ({this}) failed.");
        }

        var msg = $"failed to query using manager ({this})!";
        LoggingHandler.LogCritical(LogTitle, msg);
        throw new MyException(msg);
    }

    public void DoAll<T>(Func<X, T> somethingX, Func<Y, T> somethingY)
    {
        Do(CoreInfrastructure.GetManager(Prefix, Config.Param1, Config.Param2), somethingX);
        Do(CoreInfrastructure.GetManager(Prefix, Config.Param3), somethingY);
    }

如Damien_The_Unbeliever所述,如果创建管理器可以作为MyException的来源,则可以添加Func<TManager>代替TManager管理器:

    public T Do<T, TManager>(Func<TManager> managerCreate, Func<TManager, T> something)
    {
        try
        {
            TManager manager = managerCreate();
            if (manager != null) return something(manager);
            LoggingHandler.LogWarning(LogTitle, $"manager ({this}) is null.");
        }
        catch (MyException exp)
        {
            ExceptionHandler.HandleRecoverableException(exp, LogTitle,
                $"query on manager ({this}) failed.");
        }

        var msg = $"failed to query using manager ({this})!";
        LoggingHandler.LogCritical(LogTitle, msg);
        throw new MyException(msg);
    }

    public void DoAll<T>(Func<X, T> somethingX, Func<Y, T> somethingY)
    {
        Do(() => CoreInfrastructure.GetManager(Prefix, Config.Param1, Config.Param2), somethingX);
        Do(() => CoreInfrastructure.GetManager(Prefix, Config.Param3), somethingY);
    }

您可以更进一步,并用参数化函数替换Func<TManager>,并在其中传递PrefixConfig

答案 1 :(得分:0)

我们可以创建一个私有函数来完成大部分工作,并使现有方法适当地包装它:

private T DoInternal<T>(Func<X> getManager, Func<X, T> something)
{
    try
    {
        var manager = getManager();
        if (manager != null) return something(manager);
        LoggingHandler.LogWarning(LogTitle, $"manager ({this}) is null.");
    }
    catch (MyException exp)
    {
        ExceptionHandler.HandleRecoverableException(exp, LogTitle,
            $"query on manager ({this}) failed.");
    }

    var msg = $"failed to query using manager ({this})!";
    LoggingHandler.LogCritical(LogTitle, msg);
    throw new MyException(msg);
}
public T Do<T>(Func<X, T> something)
{
    return DoInternal(()=> CoreInfrastructure.GetManager(Prefix, Config.Param1, Config.Param2), something);
}
public T Do<T>(Func<Y, T> something)
{
    return DoInternal(()=> CoreInfrastructure.GetManager(Prefix, Config.Param3),something);
}

当然,如果那里有共同的功能(例如,允许getManager传递DoInternal吗?可能需要对Prefix进行进一步的参数设置。)

(此外,以上声明看起来都有些怀疑,仅在T中进行了参数化,而在XY中未进行参数化。在那里可能需要做一些进一步的调整)