【问题标题】:c# get repository by entity typec# 按实体类型获取存储库
【发布时间】:2017-09-07 11:41:12
【问题描述】:

我使用存储库模式设计了一些应用程序。我有一个通用存储库:

public interface IGenericRepository<T> where T : class { // ... }

public class GenericRepository <T> : IGenericRepository<T> where T : class {// ... }

例如,我有两个实体:Order 和 OrderLine。 对于实体“订单”,我只需要通用存储库方法,所以没关系。 但是对于实体“OrderLine”,我需要一些通用存储库方法和一些附加方法。因此,我创建了一个自定义存储库,它扩展了泛型:

    public interface IOrderLinesRepository : IGenericRepository<OrderLine> {...}
    public class OrderLinesRepository : GenericRepository<OrderLine>, IOrderLinesRepository 
    {
      //... this is my additional methods here
    }

但现在我想创建一个方法,它将按实体类型返回一个存储库。 如果实体有自定义存储库 - 应该重新调整它。如果不是,方法必须返回 GenericRepository。这是我尝试创建的。

public sealed class RepositoryFactory
{

    // Here is custom repository types
    private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
    {
        return new Dictionary<Type, Func<DbContext, object>>
        {
            { typeof(OrderLine), dbContext => 
                  new OrderLinesRepository(dbContext) },
        };
    }

    // Custom repository types
    private IDictionary<Type, Type> GetRepositoryTypes()
    {
        return new Dictionary<Type, Type>
        {
            { typeof(OrderLine), typeof(IOrderLinesRepository) }
        };
    }

    private Func<GoodWillDbContext, object> GetDefaultFactory<T>() 
       where T : class
    {
        return dbContext => new GenericRepository<T>(dbContext);
    }

    private Func<DbContext, object> GetFactory<T>() where T : class
    {
        Func<DbContext, object> factory;
        var factories = GetCustomFactories();
        factories.TryGetValue(typeof(T), out factory);
        return factory ?? (factory = GetDefaultFactory<T>());
    }



    public Type GetRepoType(Type type)
    {
        var types = GetRepositoryTypes();
        Type repoType;
        types.TryGetValue(type, out repoType);
        return repoType;
    }

   public object MakeRepository<U>(DbContext dbContext) where U : class
    {
        // Get repository type 
        // If custom type not found, it should be standart type
        // IGenericRepository<U>
        var type = _repositoryFactory.GetRepoType(typeof(U)) ??
         typeof(IGenericRepository<U>);
        var f = _repositoryFactory.GetFactory<U>();
        var repo = f(dbContext);
        return repo;
    }
}

但由于某种原因它不起作用。我有一些疑问: 1. MakeRepository 应该是什么类型的返回值? 2. 我应该如何转换 var repo = f(dbContext);到存储库类型?

或者也许还有其他方法可以满足我的需要?

【问题讨论】:

  • 所以应该使用GetRepoType返回的类型来查找repo?
  • 是的,你在写。
  • But it's not working for some reason.是什么原因?什么具体不起作用?
  • 我不明白,如何将对象 repo 转换为存储库类型。

标签: c# generics


【解决方案1】:

你的代码看起来真的很复杂,本来应该很简单...下面的例子只是虚拟代码,请随意调整以适应你的需要。

public static class RepositoryFactory
{
    public static IGenericRepository<T> MakeRepository<T>(DbContext context) 
        where T : class
    {
        var type = typeof(T);

        if (type == typeof(Car))
        {
            return CarRepositoryFactory.CreateCarRpository(context);
        }
        else if (type == typeof(Boat))
        {
            return BoatRepositoryFactory.CreateBoatRepository(context);
        }
    }
}

使用方法:

var myRepo = (CarRepository)RepositoryFactory.MakeRepository(new MyContext());

这类代码不应该经常修改(您不会在每次提交时添加存储库,对吗?;)),所以请帮自己一个忙,保持简单。 :)

编辑:如果您真的想保留您的代码,请在我的回复中添加评论,我希望我能做到。 :)

【讨论】:

  • 如果我需要返回的不是 IGenericReposity,而是其中的一部分,我该怎么办?正如我所讨论的那样,扩展 IGenericRepository? 的 IOrderLineRepository
  • 其实没关系。您无需返回 IGenericRepository,而是返回 object,然后您可以简单地执行以下操作:var repo = (IOrderLineRepository)RepositoryFactory.MakeRepo&lt;OrderLine&gt;();
【解决方案2】:

所以如果我理解正确,您希望能够通过实体类型获取存储库类型。我稍微修改了您的实现,并让它按我认为的那样工作。

public sealed class RepositoryFactory
{
    public static RepositoryFactory Instance = new RepositoryFactory();

    // Here is custom repository types
    private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
    {
        return new Dictionary<Type, Func<DbContext, object>>
        {
            // { typeof(IOrderLinesRepository), dbContext => new OrderLinesRepository(dbContext) },
        };
    }

    // Custom repository types
    private IDictionary<Type, Type> GetRepositoryTypes()
    {
        return new Dictionary<Type, Type>
        {
            { typeof(OrderLine), typeof(IOrderLinesRepository) }
        };
    }

    private Func<DbContext, object> GetDefaultFactory<T>()
        where T : class
    {
        return dbContext => new GenericRepository<T>(dbContext);
    }
    private Func<DbContext, object> GetFactory(Type factoryType)
    {
        if (factoryType == null) return null;
        Func<DbContext, object> factory;
        var factories = GetCustomFactories();
        factories.TryGetValue(factoryType, out factory);
        return factory;
    }
    public Type GetRepoType(Type type)
    {
        var types = GetRepositoryTypes();
        Type repoType;
        types.TryGetValue(type, out repoType);
        return repoType;
    }
    public IGenericRepository<TEntity> MakeRepositoryByEntity<TEntity>(DbContext dbContext) where TEntity : class
    {
        var type = this.GetRepoType(typeof(TEntity));
        var f = this.GetFactory(type) ?? GetDefaultFactory<TEntity>();

        var repo = f(dbContext);
        return (IGenericRepository<TEntity>)repo;
    }

    public TRepo MakeRepository<TRepo, TEntity>(DbContext dbContext)
        where TRepo : class, IGenericRepository<TEntity>
        where TEntity : class
    {
        var repo = this.MakeRepositoryByEntity<TEntity>(dbContext);
        try
        {
            return (TRepo)repo;
        }
        catch (InvalidCastException)
        {
            throw new Exception($"Registered repository for entity ${typeof(TEntity).FullName} does not implement {typeof(TRepo).FullName}");
        }
    }

}

您可以通过以下两种方式之一调用它:

var d = RepositoryFactory.Instance.MakeRepositoryByEntity<OrderLine>(dbContext);
var d2 = RepositoryFactory.Instance.MakeRepository<IOrderLinesRepository, OrderLine>(dbContext);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    相关资源
    最近更新 更多