首页 > 解决方案 > 在通用存储库使用者类中创建通用方法

问题描述

我想在通用存储库使用者类中创建通用方法。

这是我在通用存储库类中的通用方法:

public class CosmosDBRepository<T> : ICosmosDBRepository<T> where T : class
    {
     public async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByDesc, int takeCount = -1)
    
            {
                var criteria = _container.GetItemLinqQueryable<T>(true)
                    .Where(predicate)
                    .OrderByDescending(orderByDesc)
                    .ToFeedIterator();
    
                var query = criteria;
    
                var results = new List<T>();
                while (query.HasMoreResults)
                {
                    if (takeCount > -1 && results.Count >= takeCount) break;
                    results.AddRange(await query.ReadNextAsync());
                }
    
                return results;
            }
}

通用存储库消费者类:

 public class SubscriptionRepository : CosmosDBRepository<Subscription>, ISubscriptionRepository
    {
        public SubscriptionRepository(
            ICosmosDBClient client
            ) : base(client)
        {

        }

        
        public async Task<List<T>> GetSubscriptions<T, TE>(
            TE eventItem,
            params SubscriptionAction[] subscriptionAction)
                where T : Subscription
                where TE : Event
        {
            Expression<Func<T, bool>> predicate = (x) => x.EventType == eventItem.EventType
                            && x.IsActive;

            predicate = predicate.And(x => subscriptionAction.Contains(x.Action));

            if (!string.IsNullOrEmpty(eventItem.PayerNumber))
            {
                predicate = predicate.And(x => x.PayerNumber == eventItem.PayerNumber);
            }
            else if (!string.IsNullOrEmpty(eventItem.AccountNumber))
            {
                predicate = predicate.And(x => x.AccountNumber == eventItem.AccountNumber);
            }

            var result = await GetItemsAsync(predicate, o => o.PayerNumber);

            return result.ToList();
        }
    }

现在我想GetSubscriptionsSubscriptionRepository类中创建泛型方法。

您能否建议我如何实现这一目标?

目前我收到以下编译时错误:

无法从 'System.Linq.Expression<System.Func<T,bool>>' 转换为 'System.Linq.Expression.Expression<System.Func<FleetHub.Notifications.Domain.CosmosDB.Containers.Subscription,bool>>'

标签: c#generics

解决方案


这里至少有两个问题,性质相同——你试图用一个通用的方法来包装一个具体的CosmosDBRepository<Subscription>.GetItemsAsync函数。第一个可以解决将谓词更改为:

Expression<Func<Subscription, bool>> predicate = x => x.EventType == eventItem.EventType && x.IsActive; 

但它不会解决CosmosDBRepository<Subscription>.GetItemsAsync将返回集合Subscription而不是任意Subscription后代集合的问题。如果您GetSubscriptions仍然需要通用,则需要过滤和转换结果GetItemsAsync

return result.OfType<T>().ToList();

或者为方法提供一个映射器函数:

 public async Task<List<T>> GetSubscriptions<T, TE>(
        TE eventItem,
        Func<Subscription, T> mapper, 
        params SubscriptionAction[] subscriptionAction)
            where T : Subscription
            where TE : Event
    {
        .....
        return result.Select(mapper).ToList();
    }
 

推荐阅读