2

假设我有一个 .NET 程序集 A,它使用反射来加载程序集 B 和 C(也是 .NET)。这两个程序集都实现了许多大型接口(两者相同)。当在 A 中调用方法时,它会尝试让 B 完成工作。但是,B 不可靠,可能会引发异常。现在 A 有两种模式,一种将异常传播给 A 的调用者,另一种在更稳定(但性能较低)的 C 上调用匹配方法。

有没有更好的方法(更少的代码)来实现这个场景,而不是将 B 公开的所有方法包装在所有 B 接口的巨大实现中,现在才用代码包围每个调用,如下所示?程序集 B 和 C 对所选择的错误处理方法一无所知,因此它们无法实现逻辑。

public class BErrorWrapper : I1, I2, I3{
   ...
   public int DoSomeWork(int num){
      if (FailWithExceptions)
      {
         try
         {
            return B.DoSomeWork(num);
         }
         catch(MyLibException e)
         {
            return C.DoSomeWOrk(num);
         }
      }
      else
      {
         return B.DoSomeWork(num);
      }
   }
   ...
}
4

3 回答 3

2

你可以这样做,它可以节省一些重复:

public class BErrorWrapper : I1, I2, I3{
   ...
   public int DoSomeWork(int num){
      try
      {
         return B.DoSomeWork(num);
      }
      catch(MyLibException e)
      {
         if (FailWithExceptions) throw;
         return C.DoSomeWOrk(num);
      }
   }
   ...
}
于 2008-11-19T09:31:13.490 回答
1

嗯...要保存一些代码,您可以通过委托包装大多数常见签名,如下所示(请注意,我只包含核心位以保持清晰 - 但您可以简单地添加您的FailWithExceptions东西):

    static void TryWithFallback<T>(Action<T> primary, Action<T> fallback, T arg)
    {
        try
        {
            primary(arg);
        }
        catch // add your other regular code here...
        {
            fallback(arg);
        }
    }

然后,您可以通过以下方式将其重新用于实现:

    TryWithFallback(b.DoSomeWork, c.DoSomeWork, num);

显然,您可以为相关代码添加一些签名,例如:

    static TResult TryWithFallback<T, TResult>(Func<T, TResult> primary, Func<T, TResult> fallback, T arg)
    {
        try
        {
            return primary(arg);
        }
        catch
        {
            return fallback(arg);
        }
    }
于 2008-11-19T09:37:20.420 回答
1

我建议你看看使用反射和 System.CodeDom 来生成代码。最近,当我尝试为 COM 互操作程序集编写包装器时遇到了类似的问题,该程序集具有非常大的接口,其中包含许多方法的签名,其中包含我不想在客户端使用但我可以使用的参数类型轻松转换为我在客户端想要的类型。它们也是 'ref' 参数,这会使客户端代码更加冗长。这些方法具有不同数量的参数,这些参数具有我想在客户端公开的有意义的名称。

为您的包装器编写一个基类,该基类具有 A 和 B 的实例的成员。编写一个代码生成类来生成派生的包装器类。然后,代码生成应该迭代包装器应该实现的每个接口的方法,并添加一个方法和方法体以及适当的代码,以便在所需的错误处理构造中调用 A 和 B。您生成的调用 A 和 B 的代码将取决于您正在调用的方法的签名,但这并不难通过迭代正在生成或调用的方法的参数来实现。

我可以发布我的代码,但由于我正在做一些稍微不同的事情,我认为你最好回到 MSDN 或其他公共示例。我只能说,我发现这出奇的简单和健壮。

我建议您签入您的代码生成代码而不是生成的代码,并将代码生成作为构建的一部分运行。

于 2008-11-19T10:45:48.520 回答