动态链接实体以符合DRY
本文关键字:DRY 链接 实体 动态 | 更新日期: 2023-09-27 17:54:59
是否有一种方法可以动态地执行下面的操作,这样我就不必重复自己了?
var result = from c in _Entities.Cars
where c.Colour == "White"
select c;
var result = from m in _Entities.Bikes
where m.Colour == "White"
select m;
etc...
:
var entities = new List<string> {"Cars", "Bikes"};
foreach (var e in entities)
{
var result = from m in e //pseudo code
where m.Colour == "White"
select m;
}
如果Cars和Bikes实现了一个公共接口,比如IVehicle,它具有color属性,那么您可以定义一个函数:
public IEnumerable<IVehicle> GetWhiteVehicles(IEnumerable<IVehicle> vehicles) {
return vehicles.Where(p => p.Colour == "White");
}
和
var result = GetWhiteVehicles(_Entities.Cars);
var result = GetWhiteVehicles(_Entities.Bikes);
如果Cars和Bikes是从实体框架中生成的类,那么您仍然可以通过添加一个新的源文件来实现一个接口,该文件包含同名类的部分定义:
public partial class Bikes : IVehicle { }
public partial class Cars : IVehicle { }
添加一个包含color (iccolored)的接口。设置你的汽车和自行车来实现这个接口。创建和调用函数:
List<IColorful> FindByColor(IEnumerable<IColorful> list, string color)
{
List<IColorful> result = list.Where(item => item.Color == color).ToList();
return result;
}
这样写:
var entities = FindByColor(_Entities.Cars, color);
entities.AddRange(FindByColor(_Entities.Bikes, color))
应该可以:
var entities = new List<List<dynamic>> {_Entities.Cars.ToList<dynamic>(), _Entitites.Bikes.ToList<dynamic>()};
foreach (var l in entities)
{
var result = from m in l
where m.Colour == "White"
select m;
}
因此,您可以避免对业务模型进行任何更改。然而,dynamic
类型只在运行时解析,因此无法确保属性Colour
在该类型上确实存在。
首先定义一个它们都派生的基类,或者定义一个它们都实现的接口。我将从这里假设他们实现了一个IColoured
接口和一个Colour
属性。(尽管我要注意,在成员名中使用en-US是很常见的,所以颜色由Color
属性表示)。
namespace SomeNamespace
{
public partial class Cars
{
/*…*/
public string Colour { get; set; }
/*…*/
}
}
你可以有一个文件:
namespace SomeNamespace
{
public partial class Cars : IColoured
{
}
}
因为两个partial
代码片段在编译类定义时被组合在一起,你的代码只需要表明接口被实现,匹配属性在另一个文件中这一事实并不重要。
:
public static IQueryable<T> FilterByColour<T>(this IQueryable<T> source, string colour)
where T : IColoured
{
return source.Where(p => p.Colour == colour);
}
现在你可以使用_Entities.Cars.FilterByColour("white")
, _Entities.Bikes.FilterByColour("blue")
等。如果通过"white"
进行过滤是一个特别常见的情况,那么:
重要:如果你没有一个很好的理由(比如使用与EF不兼容的东西),永远不要定义这样的方法作为使用IEnumerable<>
,使用IQueryable<>
,这样它仍然被EF处理并可以在数据库上过滤,而不是从数据库中检索所有内容并在应用程序中过滤。
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.FilterByColour("white");
}
如果没有其他用途,则:
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.Where(p => p.Colour == "white");
}
。