0

所以我是泛型的新手。但是泛型似乎是减少代码的好方法。这是场景。我有一个 MVC Web API。

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

注意:id 是可选的

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

  1. 每小时设备图表
  2. 每小时用户图表
  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
}
4

3 回答 3

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>();
于 2013-02-09T19:51:52.553 回答
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();
}
于 2013-02-09T19:50:58.940 回答
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
于 2014-01-17T07:03:17.167 回答