使用泛型的最佳方法

时间:2013-02-09 19:34:56

标签: c# generics asp.net-web-api

所以我对仿制药不熟悉。但是泛型似乎是减少代码的好方法。这是场景。我有一个MVC Web API。

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

注意:id是可选的

我有几种返回类似对象的图表类型:

  1. HourlyDeviceChart
  2. HourlyUsersCharrt
  3. HourlyAvgProcessingTime 等。
  4. 我想只有一个方法来评估图表类型参数并执行相应的操作。而不是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
    }
    

3 个答案:

答案 0 :(得分: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>();

答案 1 :(得分: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();
}

答案 2 :(得分: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;
}

将它们称为:

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