0

だから私はジェネリックに不慣れです。しかし、ジェネリックはコードを減らすための優れた方法のようです。これがシナリオです。私はMVCWebAPIを持っています。

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

:idはオプションです

同様のオブジェクトを返すチャートタイプがいくつかあります。

  1. HourlyDeviceChart
  2. HourlyUsersCharrt
  3. HourlyAvgProcessingTimeなど。

チャートタイプパラメータを評価し、対応するアクションを実行するメソッドを1つだけ作成したいと思います。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

HourlyUserChartとメソッドの両方HourlyDeviceChartが同じように機能する場合、dasblinkenlightの答えは適切であり、それらを設定する1つの一般的な方法があります。2つのリポジトリメソッドで異なる方法でそれらを設定する必要がある場合は、次のようになります。

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 に答える