2013-11-24 78 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%準確的,但我希望它會指向您正確的方向。

相關問題