【问题标题】:C# Avoid Repetitive code and use GenericC# 避免重复代码并使用泛型
【发布时间】:2016-06-09 21:34:07
【问题描述】:

主题可能看起来这个问题已经发布,但我的代码 sn-p 和问题不同。 请看一看。 我有一些 20 到 22 个 Sql 表,我在我的应用程序中创建了我的 POCO 类。这些表中的每一个都有一些 4-5 个公共列,我需要在应用程序中填充一些记录,表的其余列已经由其他应用程序发送的 XML 数据填充。每个表中仅有的 4-5 个常用列我尝试填写如下应用程序。

private List<Software> GetSoftwareEntityData(Information request, DateTime scanDateTime)
{
    List<Software> Data = new List<Software>();
    int SrNo = 0;
    foreach (var item in request.Software)
    {
        Software d = new Software();
        d = item;
        d.DCDTime = DateTime.Now;
        d.LastModDTime = scanDateTime;
        d.ID = request.Id;
        d.ScanDateTime = scanDateTime;
        d.SrNo = ++SrNo;
        Data.Add(d);
    }
    return Data;
}

private List<Users> GetUsersEntityData(Information request, DateTime scanDateTime)
{
    List<Users> Data = new List<Users>();
    int SrNo = 0;
    foreach (var item in request.Users)
    {
        Users d = new Users();
        d = item;
        d.DCDTime = DateTime.Now;
        d.LastModDTime = scanDateTime;
        d.ID = request.Id;
        d.ScanDateTime = scanDateTime;
        d.SrNo = ++SrNo;
        Data.Add(d);
    }
    return Data;
}

同样,我为每个表编写了 22 个表的代码,当我处理该特定对象集时,这些函数被调用。

我怎样才能创建一个通用方法,这样我就可以摆脱22个重复代码的函数?

我也在下面发布我的信息类。

public class Information
{
 public List<Software> Software{get;set;}
 public List<Users> Users{get;set;}
}

所以现在我的 Software 和 Users 类如下所示,并带有一个名为 ICommonColumns 的接口实现。

public interface ICommonColumns
{
DateTime DCDTime{get;set;}
DateTime LastModDTime{get;set}
.....
and others common fields
}

public class Software : ICommonColumns
{
....
}

public class Users : ICommonColumns
{
....
}

【问题讨论】:

  • 你可以很容易地泛化除foreach (var item in request.Software) 之外的所有行。您可以使用通用函数处理除该行之外的所有内容,或者您​​可以使用 Reflection 来做这件事,但我不确定该怎么做。
  • 我认为在您的情况下,最好的方法是将这些字段提取到另一个表中,至少我会这样做,但是如果您使用的是旧表并且您无法更改逻辑看看这个链接,它展示了如何实现一个通用存储库:tugberkugurlu.com/archive/…
  • 所以 foreach(request.Software 中的变量项)对我来说是一个挑战。我该如何概括?
  • foreach 很困难。我会质疑在这里使用泛型的好处。您将节省 一些 代码,但会增加复杂性。就我个人而言,我会接受我认为的重复
  • 你能解释一下这是做什么的吗? Users d = new Users(); d = item; 在你的例子中?创建一个新的Users 并覆盖该对象,没有意义..

标签: c# generics


【解决方案1】:

为什么不让 POCO 实现一个接口并创建一个接受该接口实现的方法?

编辑:

public interface ISomething
{
    public DateTime DCDTime { get; set; }
    public DateTime LastModDTime { get; set; }
    public int ID { get; set; }
    public DateTime ScanDateTime { get; set; }
    public int SrNo { get; set; }
}
    private IEnumerable<T> GetSoftwareEntityData<T>(Information request, DateTime scanDateTime, Func<Information, T> someCollection)
    where T : ISomething
   {
    int SrNo = 0;

    foreach (var item in someCollection(request))
    {
        item.DCDTime = DateTime.Now;
        item.LastModDTime = scanDateTime;
        item.ID = request.Id;
        item.ScanDateTime = scanDateTime;
        item.SrNo = ++SrNo;

        yield return item;
    }
}

【讨论】:

  • 看起来不错。您能否在我的示例中发布一个示例以及一个通用示例。
【解决方案2】:

SoftwareUsers 都需要有一个约束,以确保它们有一些共同点,例如 interface 或基类。

public class BaseEntity
{
    public DateTime DCDTime { get; set; }
    public DateTime LastModDTime { get; set; }
    public DateTime ScanDateTime { get; set; }
    public int ID { get; set; }
    public int SrNo { get; set; }
}

例如,您的 Software 类将如下所示:

public class Software : BaseEntity
{
    //Some more properties
}

然后你可以像这样创建一个泛型方法:

private IEnumerable<TEntity> GetEntityData<TEntity>(int requestId, IEnumerable<TEntity> requestEntities, DateTime scanDateTime)
    where TEntity : BaseEntity, new()
{
    int SrNo = 0;

    foreach (var item in requestEntities)
    {
        TEntity d = new TEntity();
        d = item;
        d.DCDTime = DateTime.Now;
        d.LastModDTime = scanDateTime;
        d.ID = requestId;
        d.ScanDateTime = scanDateTime;
        d.SrNo = ++SrNo;

        yield return item;
    }
}

然后这样称呼它:

IEnumerable<Software> softwares = GetEntityData<Software>(request.Id, request.Software, DateTime.Now);
IEnumerable<Users> users = GetEntityData<Users>(request.Id, request.Users, DateTime.Now);

【讨论】:

  • 我认为requestEntities 类型和返回的类型不一样或者不共享一个基类类型。
  • 是的,它们不一样
  • 在您拥有的软件方法中,您正在实例化一个新的Software,然后执行以下操作:d = item;。这看起来他们是同一类型?
  • where TEntity : BaseEntity 确保传入的任何类型参数必须继承自BaseEntity,这允许您访问属性,例如DCDTimeID for例子。 new() 这里实际上不需要,所以我将其删除。
  • @MikeEason 我将如何遍历 requestEntities 并返回一组新的 IEnumerable。如果你能在我的代码中看到,我就有这样的东西。
猜你喜欢
  • 2011-04-16
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-20
  • 1970-01-01
  • 2014-03-07
相关资源
最近更新 更多