如何使用try-catch-finally重构代码

时间:2012-03-12 06:20:47

标签: c# refactoring

我必须创建一堆看起来像这样的方法。更改的内容将是方法名称,返回类型和中间标记的行 - 其余的将是相同的。是否有一种干净的方法来重构这个以便我不重复自己?

private bool CanPerform(WindowsIdentity identity, string applicationName, int operation)
{
    IAzApplication3 application = null;
    IAzClientContext3 context = null;
    try
    {
        application = this.store.OpenApplication(applicationName, null) as IAzApplication3;

        ulong token = (ulong)identity.Token.ToInt64();
        context = application.InitializeClientContextFromToken(token, null) as IAzClientContext3;

        // lines that change go here
    }
    catch (COMException e)
    {
        throw new SecurityException(string.Format("Unable to check operation '{0}'", operation), e);
    }
    finally
    {
        Marshal.FinalReleaseComObject(context);
        Marshal.FinalReleaseComObject(application);
    }
}

我意识到这可能是基本的东西,但我一个人工作,所以没有人可以问。

2 个答案:

答案 0 :(得分:6)

这听起来像委托是合适的,使用通用方法来覆盖返回类型更改:

private T ExecuteWithIdentity<T>(WindowsIdentity identity,
    string applicationName, int operation,
    Func<IAzApplication3, IAzClientContext3, T> action)
{
    IAzApplication3 application = null;
    IAzClientContext3 context = null;
    try
    {
        application = this.store.OpenApplication(applicationName, null) as IAzApplication3;

        ulong token = (ulong)identity.Token.ToInt64();
        context = application.InitializeClientContextFromToken(token, null) as IAzClientContext3;

        return action(application, context);
    }
    catch (COMException e)
    {
        throw new SecurityException(
            string.Format("Unable to check operation '{0}'", operation), e);
    }
    finally
    {
        Marshal.FinalReleaseComObject(context);
        Marshal.FinalReleaseComObject(application);
    }
}

然后,您将每个检查的代码放在一个单独的方法中,或者甚至只使用lambda表达式:

bool check = ExecuteWithIdentity(identity, "Foo", 10,
                         (application, context) => context != null);

string check = ExecuteWithIdentity(identity, "Foo", 10, SomeComplexAction);

...
private static string SomeComplexAction(IAzApplication3 application,
                                        IAzClientContext3 context)
{
    // Do complex checks here, returning whether the user is allowed to
    // perform the operation
}

您可能希望更改当前的委托类型 - 例如,不清楚operation的用途是什么。

我还强烈考虑转换而不是使用as。如果应用程序或上下文从OpenApplication / InitializeClientContextFromToken返回为非空值而不是正确的类型,您是否真的想要处理与返回的null值相同的情况?

答案 1 :(得分:1)

你可以把你的错误处理放在堆栈的稍高处,所以不是在方法中捕获并重新抛出异常,而是可以在调用方法的地方执行它吗?

如果您的方法调用都包含在Manager类中,可能会节省一些时间。如果它们只是在任何地方进行临时调用,那么自然也许不会:)

我希望这可能会有所帮助。