7

我有两种类似的方法,它们基本上只对不同的对象做同样的事情。如果可能的话,从中制作通用方法的最佳方法是什么?

两个对象:

public class StoreObject {
  int Key;
  string Address;
  string Country;
  int Latitude;
  int Longitude;
}

public class ProjectObject {
  int ProjectKey;
  string Address;
  string Description;
}

我可能想成为泛型的两种方法:

public StoreObject GetStoreByKey(int key)
{
  using (DBEntities dbe = new DBEntities())
  {
    StoreObject so = new StoreObject();
    var storeObject = (from s in dbe.StoreTables
                       where s.Key == key
                       select s).First();

    so.Key = storeObject.key;
    so.Address = storeObject.address;
    so.Country = storeObject.country;
    so.Latitude = storeObject.latitude;
    so.Longitude = storeObject.longitude;

    return so;
  }
}

public ProjectObject GetProjectByKey(int projectKey)
{
  using (DBEntities dbe = new DBEntities())
  {
    ProjectObject po = new ProjectObject();
    var projectObject = (from p in dbe.ProjectTables
                       where p.ProjectKey == projectKey
                       select p).First();

    po.Key = projectObject.p_key;
    po.Address = projectObject.p_address;
    po.Description = projectObject.p_description;

    return po;
  }
}

我必须注意:
- 我无法控制表字段的命名方式(即 p_description)。
- 例如,数据库中的 StoreTable 可能具有其他属性(如电话、邮政编码等),但我只对显示我在代码中显示的内容感兴趣。
- ProjectTable 也是如此。

4

4 回答 4

3

好吧,棘手的部分是您的实体具有不同的属性,因此使用泛型在一个方法中填充不同的属性是不值得的。但是您可以返回整个对象,然后只使用您感兴趣的属性。

public T GetEntityByKey<T>(int key)
{
  using (DBEntities dbe = new DBEntities())
  {
    return = dbe.StoreTables.Set<T>.Find(new object[] {key});
  }
}

并使用它

StoreObject so  = GetEntityByKey<StoreObject>(123);
if(so != null)
{
    int lat = so.Latitude;
} 
于 2012-04-10T00:53:21.000 回答
2

每种方法本质上都有两个不同的功能:

  1. 查询实体
  2. 将该实体映射到另一种类型

第一部分已由 Steve Mallory 解决。

对于第二部分,您可以使用映射器框架来处理将值从一个实例复制到另一个实例。由于每种类型的名称不匹配,您需要告诉它如何映射名称(在您的示例中,添加“p_”并将其设为小写)。一种可能性是Emit Mapper

如果你要排除所有的共性,它会是这样的

public TResult GetById<TResult, TEntity>(int id)
{
    using (DBEntities dbe = new DBEntities())      
    {        
        T result = dbe.StoreTables.Set<T>.Find(new object[] {key});
        var mapper = ObjectMapperManager.DefaultInstance
            .GetMapper<TEntity, TResult>(
               new DefaultMapConfig().MatchMembers((m1, m2) => "p_" + m1.ToLower() == m2));

        return mapper.Map(result);      
    }
}
于 2012-04-10T01:24:15.647 回答
2

您确实可以抽象出返回的类型,并将using.

前者是不好的做法,对等式影响不大,而后者成本高昂,可能会变得混乱。

这对于泛型来说并不是一个很好的候选者,除非你有很多类似的方法,在这种情况下,我会选择反射方法。

高温下,

呸。

于 2012-04-10T00:08:55.607 回答
2

这不太可能是您的整个“工作单元”,因此DBEntities()在每种方法中使用新的上下文可能是您问题的根源。

创建一个包含单个 Web 请求(或应用程序中的任何其他请求单元)Repository的类的实例DBEntities并且其中包含这些方法的类将是消除此处重复代码的更好方法。的范围using()然后超出了这些方法,并希望与您的 Web 请求或其他时间单位相关联。

作为一种选择,而不是创建一个新类,您还可以扩展DBEntities部分类以包含这些方法(假设这是生成的代码)。

于 2012-04-10T00:11:50.407 回答