C# 在泛型存储库使用者类中创建泛型方法
我想在泛型存储库使用者类中创建泛型方法 以下是我在泛型存储库类中的泛型方法:C# 在泛型存储库使用者类中创建泛型方法,c#,generics,C#,Generics,我想在泛型存储库使用者类中创建泛型方法 以下是我在泛型存储库类中的泛型方法: public class CosmosDBRepository<T> : ICosmosDBRepository<T> where T : class { public async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate, Exp
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;
}
}
公共类CosmosDBRepository:ICOSOMOSDBRepository其中T:class
{
公共异步任务GetItemsAsync(表达式谓词,表达式orderByDesc,int takeCount=-1)
{
var条件=_container.GetItemLinqQueryable(true)
.Where(谓词)
.OrderByDescending(orderByDesc)
.ToFeedIterator();
var查询=条件;
var results=新列表();
while(query.HasMoreResults)
{
如果(takeCount>-1&&results.Count>=takeCount)中断;
results.AddRange(wait query.ReadNextAsync());
}
返回结果;
}
}
通用存储库使用者类:
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();
}
}
公共类SubscriptionRepository:CosmosDBRepository,ISubscriptionRepository
{
公共订阅存储库(
ICosmosDBClient客户端
):基本(客户端)
{
}
公共异步任务订阅(
事件项,
参数SubscriptionAction[]SubscriptionAction)
其中T:订阅
其中TE:事件
{
表达式谓词=(x)=>x.EventType==eventItem.EventType
&&十是积极的;
predicate=predicate.And(x=>subscriptionAction.Contains(x.Action));
如果(!string.IsNullOrEmpty(eventItem.PayerNumber))
{
谓词=谓词。和(x=>x.PayerNumber==eventItem.PayerNumber);
}
如果(!string.IsNullOrEmpty(eventItem.AccountNumber))
{
谓词=谓词。和(x=>x.AccountNumber==eventItem.AccountNumber);
}
var result=await GetItemsAsync(谓词,o=>o.PayerNumber);
返回result.ToList();
}
}
现在我想在SubscriptionRepository
类中创建泛型方法GetSubscriptions
你能建议我如何做到这一点吗
目前我遇到以下编译时错误:
无法从“System.Linq.Expression”转换为
'System.Linq.Expression.Expression'
也许你应该用
Expression<Func<Subscription, bool>> predicate = (x) => x.EventType == eventItem.EventType
&& x.IsActive;
表达式谓词=(x)=>x.EventType==eventItem.EventType
&&十是积极的;
由于您使用的是泛型类型T而不是Subscription(即使您检查T应该是Subscription或子类),因此无法分配表达式
在您的例子中,我看不到在GetSubscriptions中使用泛型而不是直接使用实类型的好处
检查此示例:
public class Test
{
}
Expression<Func<Test, bool>> temp1 = (t) => true;
Expression<Func<object, bool>> temp2 = temp1;
公共类测试
{
}
表达式temp1=(t)=>true;
表达式temp2=temp1;
此示例将在第二行失败。甚至is Test是对象的子类(与.NET中的所有类一样)
编辑
如下文所述:
Func的T(第一个泛型类型参数)具有“in”关键字。这意味着:
此类型参数是逆变的。也就是说,您可以使用
指定的类型或派生较少的任何类型
因为T可以是Subscription的子级(比如说“ChildSubscription”)。
当您尝试将Func分配给Func时,您将尝试分配一个更派生的函数。这里至少有两个问题,这两个问题性质相同-您试图创建一个通用方法来包装一个具体的
cosmosdbrespository.GetItemsAsync
函数。第一个问题可以通过将谓词更改为:
Expression<Func<Subscription, bool>> predicate = x => x.EventType == eventItem.EventType && x.IsActive;
或为方法提供映射器函数:
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();
}
public异步任务GetSubscriptions(
事件项,
Func mapper,
参数SubscriptionAction[]SubscriptionAction)
其中T:订阅
其中TE:事件
{
.....
返回结果.Select(mapper.ToList();
}
问题出在哪里?是否希望该方法显示在界面中?您必须创建一个新接口,专门用于订阅存储库。@Arcord,目前我遇到编译时错误“无法从'System.Linq.Expression'转换为'System.Linq.Expression.Expression'”,我已尝试过result.OfType().Cast().ToList();但是它回来了0@RakeshKumar这意味着不存在由GetSubscriptions
返回的T
类型的实例。这并不奇怪,请举例说明如何使用mapper实现这一点?@RakeshKumar您提供了一个lambda表达式,用于从订阅中构建您的T
。像s=>newconcrete{Field1=s.SomeField1,Field2=s.SomeField2,…}
我需要创建一个自定义映射程序,而不是将该方法作为参数传递吗?
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();
}