2013-02-09 69 views
0

所以我是新的泛型。但泛型似乎是減少代碼的好方法。這裏是場景。我有一個MVC Web API。最好的方式使用泛型

http://www.google.com/{controller}/{chartType}/{id} 

注意:id爲可選

我有幾個圖表類型的返回相似的對象:

  1. HourlyDeviceChart
  2. HourlyUsersCharrt
  3. HourlyAvgProcessingTime 等。

我想只有一個方法來評估圖表類型參數並執行相應的操作。而不是8或10種方法。

我會接受,如果我的設計需要一些重構。我接受建議。這裏的想法是減少一些代碼。我討厭在Web API中暴露10個方法,然後在另一個類中使用10個更多相應的方法。看起來多餘。

一如既往,歡迎您的建議!

API公開的方法:

IEnumerable<T> GetChart(string chartType) 
{ 
    switch(chartType) 
    { 
     case "DeviceChart": 
     return repository.HourlyDeviceChart(); 
     break; 

     case "UserChart": 
     return repository.HourlyUsersChart(); 
     break; 

    } 
} 

//Then the class that handles all the work would look something like the below 

IEnumerable<HourlyDeviceChart> HourlyDeviceChart() 
{ 
    // select appropriate items from the queue 
    // populate HourlyDeviceChart object 
    // add object to list 
    // return HourlyDeviceChart list 
} 

IEnumerable<UserDeviceChart> HourlyUsersChart() 
{ 
    // do more of the same 
} 
+0

的可能重複(http://stackoverflow.com/questions/9949406/最好的方式來做這個通用的抽象類在C) – nawfal 2014-01-16 15:49:54

回答

0

如果同時HourlyUserChartHourlyDeviceChart方法相同的方式工作,然後dasblinkenlight的答案是好的,你可以有填充其中的一個通用的方法。如果您需要在兩個倉庫不同的方法填充這些,可能是像這些都會做的事:

1)

interface IHourlyChart { 
    IEnumerable<IHourlyChart> Create(); 
} 

class HourlyDeviceChart : IHourlyChart 
{ 
    public IEnumerable<IHourlyChart> Create() 
    { 
     return repository.HourlyDeviceChart(); 
    } 
} 

class HourlyUsersChart : IHourlyChart 
{ 
    public IEnumerable<IHourlyChart> Create() 
    { 
     return repository.HourlyUsersChart(); 
    } 
} 

IEnumerable<T> GetChart<T>() where T : IHourlyChart, new() 
{ 
    return (IEnumerable<T>)new T().Create(); 
} 

2)或使其一點點通過仿製藥更強類型。

interface IHourlyChart<T> where T : IHourlyChart<T> { 
    IEnumerable<T> Create(); 
} 

class HourlyDeviceChart : IHourlyChart<HourlyDeviceChart> 
{ 
    public IEnumerable<HourlyDeviceChart> Create() 
    { 
     return repository.HourlyDeviceChart(); 
    } 
} 

class HourlyUsersChart : IHourlyChart<HourlyUsersChart> 
{ 
    public IEnumerable<HourlyUsersChart> Create() 
    { 
     return repository.HourlyUsersChart(); 
    } 
} 

IEnumerable<T> GetChart<T>() where T : IHourlyChart, new() 
{ 
    return new T().Create(); 
} 

3)或一些反思,這仍然比你的類型檢查好:

IEnumerable<T> GetChart<T>() where T : IHourlyChart, new() 
{ 
    //find necessary method and invoke. may be: 
    return repository.GetType() 
        .GetMethods() 
        .Single(x => x.ReturnType == typeof(IEnumerable<T>)) 
        .Invoke(repository, new object[0]) as IEnumerable<T>; 
} 

4)最糟糕的情況下,請輸入您的通用方法內部檢查,但檢查在類型本身上,不是任何非常脆弱的魔術串。

IEnumerable<T> GetChart<T>() 
{ 
    if (typeof(T) == typeof(HourlyDeviceChart)) 
     return (IEnumerable<T>)repository.HourlyDeviceChart(); 
    else if (typeof(T) == typeof(HourlyUsersChart)) 
     return (IEnumerable<T>)repository.HourlyUsersChart(); 

    // throw; 
} 

叫他們都喜歡:?要做到這一點一般抽象類在C#中的最佳方式]

var chartables = GetChart<HourlyUserChart>(); //etc 
0

您應該能夠通過使用新的界面,將約束你的方法來做到這一點GetChart

//Interface with a Type parameter to specify the return type of the method 
public interface IChart<T> 
{ 
    IEnumerable<T> HourlyChart(); 
} 

//How to implement the interface 
public class HourlyDeviceChart : IChart<HourlyDeviceChart> 
{ 
    public static IEnumerable<HourlyDeviceChart> HourlyChart() 
    { 
     //Do work 
    } 
} 

//Your new method with a constraint applied 
IEnumerable<T> GetChart<T>(string chartType) where T : IChart<T> 
{ 
    return T.HourlyChart(); 
} 
+0

啊kewl!我會給出一個 – 2013-02-09 20:05:19

+1

我有點困惑與約束的方法。 'T'沒有點運算符。 – 2013-02-09 21:27:51

+0

對不起,我忘記了該方法的靜態關鍵字。請參閱編輯。 – Khan 2013-02-11 02:21:12

1

您可以使用泛型像此:

interface IChart { 
    bool IsCharItemNeeded(IChartItem item); 
    void AddChartItem(IChartItem item); 
} 

IEnumerable<T> Charts<T>() where T : new, IChart { 
    var res = List<T>(); 
    foreach (QueueCommand command in MyBigQueue) { 
     var chart = new T(); 
     foreach (IChartItem item in command) { 
      if (chart.IsCharItemNeeded(item)) { 
       chart.AddChartItem(item); 
      } 
     } 
     res.Add(chart); 
    } 
    return res; 
} 

所有圖表類型都需要執行常見的IChart接口。 where T : new, IChart行提供了一個約束,可讓您致電new T();爲此,所有圖表類還必須實現無參數構造函數。現在

您可以使用通用代碼:

IEnumerable<UserChart> userCharts = Charts<UserChart>(); 
IEnumerable<DeviceChart> deviceCharts = Charts<DeviceChart>();