2015-02-23 41 views
0

我有一种方法可以根据给定的参数从不同的存储库中检索数据。简化方法从通用存储库检索数据

private async Task<string> GetByIdFrom(EntityArgs args) 
{ 
    string content = null; 
    switch (args.CollectionName.ToLowerInvariant()) 
    { 
     case Common.WorkingSite: 
      var workingsite = await (new Repository<WorkingSite>()) 
       .GetByKeyAsync(args.Id); 
      if (workingsite != null) 
       content = workingsite.Content; 
      break; 
     case Common.ProductInstruction: 
      var productInfo = await (new Repository<ProductInstruction>()) 
       .GetByKeyAsync(args.Id); 
      if (productInfo != null) 
       content = productInfo.Content; 
      break; 
     case Common.Resource: 
      var resource = await (new Repository<Resource>()) 
       .GetByKeyAsync(args.Id); 
      if (resource != null) 
       content = resource.Content; 
      break; 
     default: 
      Logger.Warn("GetById(): Table {0} not found", args.CollectionName); 
      break; 
    } 
    return content; 
} 

正如你可以看到switch是所有关于重复和args.Id如果EntityArgs所有有效的cases回报Content。内容始终是复杂的JSON。

CollectionName属性为string,因为请求来自JavaScript客户端; CollectionName只是在.NET部件上标识SQLite表。

以上所有的Repository<T>类都实现了相同的抽象基Entity

[JsonObject] 
public abstract class Entity 
{ 
    protected Entity() 
    {} 

    [PrimaryKey] 
    [JsonProperty(PropertyName = "id")] 
    public int Id { get; set; } 

    [JsonIgnore] 
    public string Content { get; set; } 
} 

库是这样实现的,在那里是SQLiteDataProvider包装纸围绕SQLite-net ORM,连接到本地数据库SQLite

public class Repository<T> where T : new() 
{ 
    private readonly Logger _logger = LogManager.GetCurrentClassLogger(); 

    /// <summary> 
    /// Get by primary key 
    /// </summary> 
    public virtual async Task<T> GetByKeyAsync(object key) 
    { 
     var item = default(T); 

     try 
     { 
      item = await SQLiteDataProvider.Connection.GetAsync<T>(key); 
     } 
     catch (Exception e) 
     { 
      if ((e is InvalidOperationException) && e.Message.Contains("no elements")) 
      { 
       _logger.Info("GetByKeyAsync<{0}> - {1}", (typeof(T)).Name, e.Message); 
      } 
      else 
      { 
       _logger.Error(e); 
       throw;  
      } 
     } 
     return item; 
    } 

    // ...other methods 
} 

我敢肯定,我应该能够摆脱整个switch声明并调用类似

var item = await (new Repository<Entity>()).GetByKeyAsync(args.Id); 
return item != null ? item.Content : null; 

...当然以上都不行,因为我需要知道与底层数据库表对应的具体类。

我只是无法绕过它。想法?

+0

原始代码似乎很清楚 - 你为什么要这样做? – Hogan 2015-02-23 16:56:17

+0

罗特的原因。其中一个是单元测试,我只想通过模拟Repository 。 – 2015-02-23 16:59:22

回答

1

Sicne所有类型的实现Entity,您可以制作一个通用方法,要求type参数从它继承,因此您可以访问Content属性。

private async Task<string> GetByIdFrom<T>(EntityArgs args) 
    where T : Entity 
{ 
    T entity = await (new Repository<T>()).GetByKeyAsync(args.Id); 
    if (entity != null) 
     return entity.Content; 

    return null; 
} 

请注意,您仍然需要包含您的开关,您选择关注基于args.CollectionName其路径的非泛型方法。但至少它变得更加简洁:

private async Task<string> GetByIdFrom(EntityArgs args) 
{ 
    switch (args.CollectionName.ToLowerInvariant()) 
    { 
     case WorkingSite: 
      return GetByIdFrom<WorkingSite>(args); 
     case ProductInstruction: 
      return GetByIdFrom<ProductInstruction>(args); 
     case Resource: 
      return GetByIdFrom<Resource>(args); 
     default: 
      Logger.Warn("GetById(): Table {0} not found", args.CollectionName); 
      break; 
    } 
} 
+0

谢谢,我需要试试这个。更好的是,我希望有一种'公共虚拟RepoResolver'方法返回正确的存储库,我可以在单元测试时重写。 – 2015-02-23 17:04:25

+0

你也可以这样做,但这并不能完全帮助你从实体中检索内容。您可能需要一个存储库的接口,然后返回一个实体;但只返回*实体(而不是特定子类型)的存储库并不真正有用(除了访问内容) – poke 2015-02-23 17:14:15

相关问题