【问题标题】:Removing code duplication in methods that looks the same but works with different types删除看起来相同但适用于不同类型的方法中的代码重复
【发布时间】:2013-11-24 13:36:22
【问题描述】:

我有两个名为Run 的方法看起来几乎相同,但它们适用于不同的类型:

public string Run<T>(IEnumerable<T> items) 
{
    // ... Code

    var serializer = new ObjectSerializer<T>();
    var headers = serializer.SerializeHeaders(items);

    // ... Code

    foreach (var item in items)
    {
        var values = serializer.SerializeValues(item);

        // ... Code
    }

    // ... Code
}


public string Run<T>(IEnumerable<Wrapper<T>> items) 
{
    // ... Code

    var serializer = new ObjectWrapperSerializer<T>();
    var headers = serializer.SerializeHeaders(items);

    // ... Code

    foreach (var item in items)
    {
        var values = serializer.SerializeValues(item);

        // ... Code
    }

    // ... Code
}

public class ObjectSerializer<T>
{
    public string[] SerializeHeaders(IEnumerable<T> items) { ... }
    public string SerializeValues(T item) { ... }
}

public class ObjectWrapperSerializer<T>
{
    public string[] SerializeHeaders(IEnumerable<Wrapper<T>> items) { ... }
    public string SerializeValues(Wrapper<T> item) { ... }
}

所有// ... Code 部分在两种方法中都是相同的。 Wrapper&lt;T&gt; 有一个 T 的实例,但除此之外它们没有任何共同点。

我想删除重复项,但我不知道该怎么做。

有什么建议吗?

【问题讨论】:

    标签: c# code-duplication


    【解决方案1】:

    如果唯一不同的是所需的序列化程序,您可以将其作为参数传递吗?像这样的:

    public class Runner    
    {
        private string Run<T>(IEnumerable<T> items, IObjectSerializer<T> serializer) 
        {
            // ... Code
    
            var headers = serializer.SerializeHeaders(items);
    
            // ... Code
    
            foreach (var item in items)
            {
                var values = serializer.SerializeValues(item);
    
                // ... Code
            }
    
            // ... Code
        }
    
        public string Run<T>(IEnumerable<T> items)
        {
            return Run(items, new ObjectSerializer<T>());
        }
    
        public string Run<T>(IEnumerable<Wrapper<T>> items)
        {
            return Run(items, new ObjectWrapperSerializer<T>());
        }
    }        
    public interface IObjectSerializer<T>
    {
        string[] SerializeHeaders(IEnumerable<T> items);
        string SerializeValues(T item);
    }
    
    public class ObjectSerializer<T>: IObjectSerializer<T>
    {
        public string[] SerializeHeaders(IEnumerable<T> items) { ... }
        public string SerializeValues(T item) { ... }
    }
    
    public class ObjectWrapperSerializer<T> : IObjectSerializer<Wrapper<T>>
    {
        public string[] SerializeHeaders(IEnumerable<Wrapper<T>> items) { ... }
        public string SerializeValues(Wrapper<T> item) { ... }
    }
    

    (没有可用的 Visual Studio,所以可能不是 100% 正确!)

    【讨论】:

      【解决方案2】:

      如果你看你的逻辑,第二种方法是第一种方法的特例:如果 T 是类似于 Wrapper 的东西,则做其他事情(ObjectWrapperSerializer);否则做正常的事情(ObjectSerializer)。

      所以想法是,您希望通过查看 T 来动态决定在运行时要做什么。您是如何做到的?反思!

      if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Wrapper<>)){
          Type u = typeof(T).GetGenericArguments()[0]; //u is the type in Wrapper<U>
          MethodInfo method = TheGenericWrapperMethod;
          MethodInfo gMethod = method.MakeGenericMethod(new Type[] { u });
          gMethod.Invoke();
      } else {
          //do the normal thing
      }
      

      或者,您可以研究工厂模式:创建一个工厂类,该类在运行时生成 ObjectSerializer 或 ObjectWrapperSeralizer 实例(当然,您必须有某种契约,如继承或接口或抽象类等)。

      代码并非 100% 准确,但我希望它能为您指明正确的方向。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-10-01
        • 2022-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多