【问题标题】:Use a Template method in place of repeated code使用模板方法代替重复代码
【发布时间】:2023-03-07 22:03:01
【问题描述】:

我有 4 种代码相似的方法

private void LogExceptions(ObjA.Input input, int customerId)
{
    //ObjA is a big object, thats why I try not to send the whole object in this method
    Log(input);
    Log(ObjA.Exceptions);
}

private void LogExceptions(ObjB.Input input, int customerId)
{
    //ObjB is a big object, thats why I try not to send the whole object in this method
    Log(input);
    Log(ObjB.Exceptions);
}

等等

我无法使其成为模板方法,例如

private void LogExceptions<T1,T2>(T1 input, int customerId) whereas     T1:ObjA.Input,ObjB.Input
{
    Log(T1);
    Log(T2);
}

怎么做或有其他方法吗? 提前感谢任何帮助。

我不认为我的问题有助于获得正确的答案.... 这是确切的代码....

    private void LogExceptions(AccARef.Response response)
    {
        StringBuilder sbErrors = null;

        if (response.ValMethod != null && response.ValMethod.IsValid == false)
        {
            if (response.ValMethod.Errors.Count() > 0)
            {
                sbErrors = new StringBuilder();
                foreach (AccARef.Exception exp in response.ValMethod.Errors)
                {
                    sbErrors.Append(" * " + exp.Message + exp.StackTrace + " ");
                    Console.WriteLine(strError.ToString())
                }
            }
        }
    }

    private void LogExceptions(AccBRef.Response response)
    {
        StringBuilder sbErrors = null;

        if (response.ValMethod != null && response.ValMethod.IsValid == false)
        {
            if (response.ValMethod.Errors.Count() > 0)
            {
                sbErrors = new StringBuilder();
                foreach (AccBRef.Exception exp in response.ValMethod.Errors)
                {
                    sbErrors.Append(" * " + exp.Message + exp.StackTrace + " ");
                    Console.WriteLine(strError.ToString())
                }
            }
        }
    }

现在 AcctBRef 和 A​​cctARef 不能实现通用接口,因为它们不是我的对象。或者如果它们不是我的东西,我还能把它们装饰成我的吗?

【问题讨论】:

  • 您对“发送整个对象”的评论是什么意思?类实例是passed by value-reference,这意味着无论对象有多大,在方法之间传递的数据(指针)都非常少。
  • ObjB.Exceptions 是静态调用吗?
  • 另外,“Input”是 ObjA 和 ObjB 的内部类吗??
  • ObjA.Exceptions 只是一个示例,因为我无法输入对您没有意义的真实代码。
  • Input 是一个内部类,但它们都是独立的,来自不同的命名空间,但具有完全相同的属性。我无法更改它们或具有通用界面的原因,因为它们来自我无法控制的服务响应。

标签: c# templates generics reusability


【解决方案1】:

我的感觉是,如果有 4 种方法并且它们没有相同的方法签名,它完全没问题,它并不总是必须是通用的,它也必须是可读的。

如果你只需要Log(OneofTheTypeWhichYouKnowWhenCallingTheMethod),你为什么要打4个电话Log(T1),Log(T2),Log(T3),Log(T4)

话虽如此,您总是可以像您的情况一样进行反思。

【讨论】:

    【解决方案2】:

    您不能将 Type 参数传递给 Log 方法。你必须传递一个类型参数的实例。

    尝试以下:

     private void LogExceptions<T1, T2>(T1 input, T2 exceptions, int customerId) 
        {
            Log(input);
            Log(exceptions);
        }
    

    【讨论】:

      【解决方案3】:

      在这种情况下,如果 ObjA 和 ObjB 继承自同一个基类或接口,您甚至不需要泛型。

      如果你有

      interface IBaseClass 
      {
         IEnumerable<Something> Exceptions {get;set;}
         InputType Input {get;set;}
      }
      class A : IBaseClass {}
      class B : IBaseClass {}
      

      您可以将其用于您的 LogExceptions 签名:

      void LogExceptions(IBaseClass obj, int CustomerId) 
      {
         Log(obj.Exceptions);
         Log(obj.Input);
      }
      

      如果他们从一个通用接口继承,那么我建议他们应该这样做。

      【讨论】:

      • 我知道这个技巧...但是 ObjA 和 ObjB 不受我的控制,尽管它们具有完全相同的属性...它们是不同的,因为它们来自第 3 方服务。
      • 那么在没有反射的情况下,你会被每个 ObjA/ObjB 的覆盖所困。为每种类型添加一个覆盖,在这种情况下看起来更干净。
      猜你喜欢
      • 2014-01-23
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 2018-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多