实现具有两个不实现任何接口的 clas 的通用比较器



我正在开发一个带有 ASP.NET Core 2.0 和 C# 的 Angular 应用程序

我的大多数控制器都有这种方法:

[HttpPost("[action]")]
public void Save([FromBody] List<Models.LinePresentation> lines)
{
    bool hasChanges = false;
    List<Models.LinePresentation> newLines = 
        lines
            .Where(l => l.LineId == 0)
            .ToList();
    if ((newLines != null) && (newLines.Count > 0))
    {
        hasChanges = true;
        foreach(Models.LinePresentation newLine in newLines)
        {
            Line newDbLine = new Line()
            {
                LineReferenceId = newLine.LineReferenceId,
                Name = newLine.Name
            };
            _context.Line.Add(newDbLine);
        }
    }
    List<Line> currentLines = _context.Line.ToList();
    foreach (Line dbLine in currentLines)
    {
        Models.LinePresentation modLine = 
            lines.FirstOrDefault(x => x.LineId == dbLine.LineId);
        if (modLine == null)
        {
            _context.Line.Remove(dbLine);
            if (!hasChanges)
                hasChanges = true;
        }
        else if ((dbLine.LineReferenceId != modLine.LineReferenceId) ||
                    (dbLine.Name != modLine.Name))
        {
            dbLine.LineReferenceId = modLine.LineReferenceId;
            dbLine.Name = modLine.Name;
            _context.Line.Update(dbLine);
            if (!hasChanges)
                hasChanges = true;
        }
    }
    if (hasChanges)
        _context.SaveChanges();
}

我可以更改类Models.LinePresentationLine,并将其与两个泛型类一起使用。

我想我可以用像DbSet<T>这样的通用 DbSet 更改 DbSet _context.Line(或者我错了)。

我在这里的问题,如果我必须LineLinePresentation进行比较.就像我在代码中所做的那样:

else if ((dbLine.LineReferenceId != modLine.LineReferenceId) ||
         (dbLine.Name != modLine.Name))

这些类是:

public class Line : IEquatable<Line>
{
    public int LineId { get; set; }
    public string Name { get; set; }
    public string LineReferenceId { get; set; }
    public ICollection<Batch> Batch { get; set; }
}
public class LinePresentation
{
    public int LineId { get; set; }
    public string Name { get; set; }
    public string LineReferenceId { get; set; }
}

有没有办法创建一个接口来比较这两个类?

我不这么认为,因为LineLinePresentation没有实现任何接口,我不想使用反射。

如果您的LinePresentation是表示层实体,Line是业务域实体,那么直接比较它们不是一个好的做法。您最好先通过一些转换器将LinePresentation转换为Line,然后它们在域实体上实现比较器

尽管LineLinePresentation是非常相似的类,但根据我的经验,让它们实现一些通用接口并不是很方便,例如 ILine因为它使分离层的整个想法变得毫无用处(这个想法是独立于域和存储来改变表示方式,不是吗?您迟早会想要更改演示文稿,并且如果都实现相同的接口,则无法在不影响业务实体和可能的数据库实体的情况下做到这一点。

所以我建议你的代码看起来像

[HttpPost("[action]")]
public void Save([FromBody] List<Models.LinePresentation> lines)
{
    Save(lines.Select(l=>new Line {LineId = l.LineId, Name = l.Name, LineReferenceId = l.LineReferenceId}))
}
private void Save(IEnumerable<Line> lines)
{
    // Most of your code goes here slightly modified to work with business objects
}

稍后,可以将方法Save(IEnumerable<Line>)提取到业务层逻辑中,并可能在控制器中重用。

如果您需要做的就是提供一个在相等属性意义上检查"相等"的方法,则可以使用扩展方法执行此操作,这样您就不必修改任何一个类。

public static class LineExtensions
{
    public static bool Matches(this Line line, LinePresentation presentation)
    {
        return line.LineReferenceId == presentation.LineReferenceId
               && line.Name == presentation.Name;
    }
}

这在技术上与您现在正在做的事情没有什么不同。它只是移动它,删除一些潜在的重复,并且可能使其更具可读性,因为扩展方法的名称可以传达意图。

最新更新