我用数据表加载了10个不同的List
//List to be load
public static List<AircraftModel> Aircraft = new List<AircraftModel>();
public static List<AirlineModel> Airline = new List<AirlineModel>();
//Method to load the list Aircraft with the datatable
public void LoadAircraft(DataTable data)
{
foreach (DataRow row in data.Rows)
{
Aircraft.Add(new AircraftModel
{
Id = Int32.Parse(row["id"].ToString()),
Registration = row["registration"].ToString(),
Capacity = Int32.Parse(row["capacity"].ToString()),
Type = row["type"].ToString()
});
}
}
//Method to load the List Airline with datatable
public void LoadAirline(DataTable data)
{
foreach (DataRow row in data.Rows)
{
Airline.Add(new AirlineModel
{
Code = row["code"].ToString(),
AirlineName = row["name"].ToString()
});
}
}
是否可以使用这样的通用方法来优化我的代码:
//call method to load the List
GetData<AircraftModel>(Aircraft, datatable);
GetData<AirlineModel>(Airline, datatable);
//Unique generic method to load the 10 List < T >
public void GetData<T>(List< T > ListToBeLoad, DataTable table)
where T : class, new()
{
foreach (DataRow row in table.Rows)
{
ListToBeLoad.Add( new T
{
......
HELP NEEDED PLEASE
......
}
}
}
提前感谢您的答复和主张
西里尔
答案 0 :(得分:3)
您有两种方法,可以创建一个映射方法并将其作为参数传递,也可以使用AutoMapper。
这里是第一种解决方案的2个示例(没有AutoMapper)
填充到现有列表的示例
PopulateList(list, dataTable, (row) =>
new AircraftModel
{
Id = int.Parse(row["id"].ToString()),
Registration = row["registration"].ToString(),
Capacity = int.Parse(row["capacity"].ToString()),
Type = row["type"].ToString()
}
);
public static void PopulateList<T>(List<T> list, DataTable data, Func<DataRow, T> mapFunc)
where T : new()
{
foreach (DataRow row in data.Rows)
{
list.Add(mapFunc(row));
}
}
创建新列表并映射行的示例。
var list2 = Map(dataTable, (row) =>
new AircraftModel
{
Id = int.Parse(row["id"].ToString()),
Registration = row["registration"].ToString(),
Capacity = int.Parse(row["capacity"].ToString()),
Type = row["type"].ToString()
}
);
public static IEnumerable<T> Map<T>(DataTable data, Func<DataRow, T> mapFunc)
where T : new()
{
foreach (DataRow row in data.Rows)
{
yield return mapFunc(row);
}
}
答案 1 :(得分:1)
您可能已经注意到,问题在于您需要了解列以获取正确的数据,并需要了解属性以将其存储在正确的位置。因此,您的代码需要了解每个单独的类-很好:您将不会摆脱此代码。
通常,当您要构造某些东西时,您可能会想到一个工厂,即能够构造特定类型实例的方法(或类)。在您的情况下,工厂 class 可能如下所示:
public abstract class Factory<T>
{
public T Create(DataRow row);
}
现在,您要做的下一步就是为您要创建的每种类型创建特定的实例,例如
public sealed class AirlineModelFactory : Factory<AirlineModel>
{
public override AirlineModel Create(DataRow row)
{
return new AirlineModel
{
Code = row["code"].ToString(),
AirlineName = row["name"].ToString()
};
}
}
现在样板代码是这样的:
public void GetData<T>(List<T> list, DataTable table, Factory<T> factory)
where T : class, new()
{
foreach (DataRow row in table.Rows)
{
list.Add(factory.Create(row));
}
}
,您可以称其为
GetData(AirlineList, table, new AirlineModelFactory());
GetData(AirpoirtList, table, new AirportModelFactory());
// etc.
尽管有争议,但是您可能希望保留工厂实例(甚至注入它们以进行控制反转)以避免new
。
但是,您将注意到,仍然需要为N
类型创建N
类/方法。
要使事情自动化更多,您可以在工厂中引入“通用”基类,例如
public abstract class GenericFactory
{
public abstract object CreateObject(DataRow row);
}
然后实施
public abstract class Factory<T> : GenericFactory
{
public override object CreateObject(DataRow row) => Create(row);
// ...
}
有了这个,您可以想到一个查询字典Dictionary<Type, GenericFactory>
。通过选择正确的类型,然后转换为正确的T
,您将获得正确的实例。但是,这是一种服务定位器模式-一种代码气味,因为缺少字典中的注册会在运行时导致错误-但根据您的需要,它仍然可能会有所帮助。