2013-11-24 49 views
1

我有两个方法称为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<T>有一个T的实例,但除此之外它们没有任何共同之处。

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

有什么建议吗?

回答

3

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

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%正确的!)

0

如果你看一下你的逻辑,第二种方法是第一种方法的一个特例:如果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%准确的,但我希望它会指向您正确的方向。

相关问题