所以我对仿制药不熟悉。但是泛型似乎是减少代码的好方法。这是场景。我有一个MVC Web API。
http://www.google.com/{controller}/{chartType}/{id}
注意:id是可选的
我有几种返回类似对象的图表类型:
我想只有一个方法来评估图表类型参数并执行相应的操作。而不是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 :(得分: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)
如果HourlyUserChart
和HourlyDeviceChart
方法都以相同的方式工作,那么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