【问题标题】:Generic method extraction通用方法提取
【发布时间】:2017-08-19 17:50:37
【问题描述】:

我正在编写 DbSets 的模拟并最终编写了一系列这样的代码。

int rowCount = 0;
var maxOrderId = EntityContainer.Set<Order>().Max(a => a.Id);
var newOrders = EntityContainer.Set<Order>().Where(a =>a.Id == 0);
foreach (var order in newOrders)
{
    order.Id = ++maxOrderId;
    rowCount++;
}

var maxServiceId = EntityContainer.Set<Service>().Max(a => a.Id);
var newServices = EntityContainer.Set<Service>().Where(a => a.Id == 0);
foreach (var service in newServices)
{
    service.Id = ++maxServiceId;
    rowCount++;
}

此列表中有更多实体。有没有办法可以将这些提取到通用方法? 比如:

int GenerateID<Order>();

我尝试使用 dynamic,但编译器抱怨 lambda 表达式中不允许动态。

【问题讨论】:

标签: c# .net generics


【解决方案1】:

您必须确保您的对象实现如下接口:

interface IItem
{
    int Id { get; set; }
}

GenerateId 方法将如下所示:

int GenerateID<T>(int rowCount) where T : IItem
{
    var maxId = EntityContainer.Set<T>().Max(a => a.Id);
    var newItems = EntityContainer.Set<T>().Where(a => a.Id == 0);
    foreach (T item in newItems)
    {
        item.Id = ++maxId;
        rowCount++;
    }

    return rowCount;
}

编辑

为避免添加接口,您可以传递访问器函数/操作:

int GenerateId<T>(int rowCount, Func<T, int> getIdFunc, Action<T, int> setIdFunc)
    where T : class 
{
    var maxId = EntityContainer.Set<T>().Max(getIdFunc);
    var newItems = EntityContainer.Set<T>().Where(a => getIdFunc.Invoke(a) == 0);
    foreach (T item in newItems)
    {
        setIdFunc.Invoke(item, maxId++);
        rowCount++;
    }

    return rowCount;
}

然后调用为:

rowCount = GenerateId<Order>(rowCount, o => o.Id, (o, id) => o.Id = id);
rowCount = GenerateId<Service>(rowCount, o => o.Id, (o, id) => o.Id = id);

【讨论】:

  • a.Id 不会是有效成员,除非我们使用具有成员作为 Id 的类/接口的约束
  • 这行不通,因为没有人说T 有一个Id。那么T一定是某个接口。
  • 这是否意味着,我必须使用 IItem 接口扩展我的所有类??
  • 我期待一些基于反射的技术来帮助我......我很擅长反射......
【解决方案2】:

如果我理解正确,您的模型需要自动增量 ID。

请看这个answer

另外,如果你想设置启动 id,只需像这样使用 smth

public class Model
{
    private static int m_Counter = 0;
    //
    public static ResetCounter(int start)
    {
        m_Counter=start;
    }
    public int Id { get; set; }

    public Model()
    {
        this.Id = System.Threading.Interlocked.Increment(ref m_Counter);
    }
}

并使用

Model.ResetCounter(maxServiceId)//optionally 
new Model {} //now When you create new object Model.Id should increment by itself

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多