动态链接实体以符合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;
}

动态链接实体以符合DRY

如果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属性表示)。

所以,假设你的Cars类是由EF创建的:
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");
}