40 changed files with 762 additions and 12 deletions
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Linq.Dynamic.Queryable\LINGYUN.Linq.Dynamic.Queryable.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
[DependsOn(typeof(AbpDddApplicationContractsModule))] |
|||
public class AbpDynamicQueryableApplicationContractsModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public class DynamicParamterDto |
|||
{ |
|||
public string Name { get; set; } |
|||
public string Description { get; set; } |
|||
public string Type { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using LINGYUN.Linq.Dynamic.Queryable; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public class GetListByDynamicQueryableInput : PagedAndSortedResultRequestDto |
|||
{ |
|||
[Required] |
|||
public DynamicQueryable Queryable { get; set; } |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public interface IDynamicQueryableAppService<TEntityDto> |
|||
{ |
|||
/// <summary>
|
|||
/// 获取可用字段列表
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
Task<ListResultDto<DynamicParamterDto>> GetAvailableFieldsAsync(); |
|||
/// <summary>
|
|||
/// 根据动态条件查询数据
|
|||
/// </summary>
|
|||
/// <param name="input"></param>
|
|||
/// <returns></returns>
|
|||
Task<PagedResultDto<TEntityDto>> GetListAsync(GetListByDynamicQueryableInput input); |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpDynamicQueryableApplicationContractsModule), |
|||
typeof(AbpDddApplicationModule))] |
|||
public class AbpDynamicQueryableApplicationModule : AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.Auditing; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public class AbpDynamicQueryableOptions |
|||
{ |
|||
public List<string> IgnoreFields { get; } |
|||
|
|||
public AbpDynamicQueryableOptions() |
|||
{ |
|||
IgnoreFields = new List<string> |
|||
{ |
|||
nameof(IMultiTenant.TenantId), |
|||
nameof(IDeletionAuditedObject.IsDeleted), |
|||
nameof(IDeletionAuditedObject.DeleterId), |
|||
nameof(IDeletionAuditedObject.DeletionTime), |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public abstract class DynamicQueryableAppService<TEntity, TEntityDto> : ApplicationService, IDynamicQueryableAppService<TEntityDto> |
|||
{ |
|||
/// <summary>
|
|||
/// 获取可用字段列表
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public virtual Task<ListResultDto<DynamicParamterDto>> GetAvailableFieldsAsync() |
|||
{ |
|||
var options = LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDynamicQueryableOptions>>().Value; |
|||
|
|||
var entityType = typeof(TEntity); |
|||
var dynamicParamters = new List<DynamicParamterDto>(); |
|||
|
|||
var propertyInfos = entityType |
|||
.GetProperties() |
|||
.Where(p => !options.IgnoreFields.Contains(p.Name)); |
|||
|
|||
foreach (var propertyInfo in propertyInfos) |
|||
{ |
|||
// 字段本地化描述规则
|
|||
// 在本地化文件中定义 DisplayName:PropertyName
|
|||
var localizedProp = L[$"DisplayName:{propertyInfo.Name}"]; |
|||
dynamicParamters.Add( |
|||
new DynamicParamterDto |
|||
{ |
|||
Name = propertyInfo.Name, |
|||
Type = propertyInfo.PropertyType.FullName, |
|||
Description = localizedProp.Value ?? propertyInfo.Name |
|||
}); |
|||
} |
|||
|
|||
return Task.FromResult(new ListResultDto<DynamicParamterDto>(dynamicParamters)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据动态条件查询数据
|
|||
/// </summary>
|
|||
/// <param name="input"></param>
|
|||
/// <returns></returns>
|
|||
public async virtual Task<PagedResultDto<TEntityDto>> GetListAsync(GetListByDynamicQueryableInput input) |
|||
{ |
|||
Expression<Func<TEntity, bool>> condition = (e) => true; |
|||
|
|||
condition = condition.DynamicQuery(input.Queryable); |
|||
|
|||
var totalCount = await GetCountAsync(condition); |
|||
var entities = await GetListAsync(condition, input); |
|||
|
|||
return new PagedResultDto<TEntityDto>(totalCount, |
|||
MapToEntitiesDto(entities)); |
|||
} |
|||
|
|||
protected abstract Task<int> GetCountAsync(Expression<Func<TEntity, bool>> condition); |
|||
|
|||
protected abstract Task<List<TEntity>> GetListAsync( |
|||
Expression<Func<TEntity, bool>> condition, |
|||
PagedAndSortedResultRequestDto pageRequest); |
|||
|
|||
protected virtual List<TEntityDto> MapToEntitiesDto(List<TEntity> entities) |
|||
{ |
|||
return ObjectMapper.Map<List<TEntity>, List<TEntityDto>>(entities); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,18 @@ |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpDynamicQueryableApplicationContractsModule), |
|||
typeof(AbpAspNetCoreMvcModule))] |
|||
public class AbpDynamicQueryableHttpApiModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
//PreConfigure<IMvcBuilder>(mvcBuilder =>
|
|||
//{
|
|||
// mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpDynamicQueryableHttpApiModule).Assembly);
|
|||
//});
|
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace LINGYUN.Abp.Dynamic.Queryable; |
|||
|
|||
public abstract class DynamicQueryableControllerBase<TEntityDto> : AbpControllerBase, IDynamicQueryableAppService<TEntityDto> |
|||
{ |
|||
protected IDynamicQueryableAppService<TEntityDto> DynamicQueryableAppService { get; } |
|||
|
|||
protected DynamicQueryableControllerBase( |
|||
IDynamicQueryableAppService<TEntityDto> dynamicQueryableAppService) |
|||
{ |
|||
DynamicQueryableAppService = dynamicQueryableAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("available-fields")] |
|||
public Task<ListResultDto<DynamicParamterDto>> GetAvailableFieldsAsync() |
|||
{ |
|||
return DynamicQueryableAppService.GetAvailableFieldsAsync(); |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("search")] |
|||
public Task<PagedResultDto<TEntityDto>> GetListAsync(GetListByDynamicQueryableInput input) |
|||
{ |
|||
return DynamicQueryableAppService.GetListAsync(input); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,11 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,53 @@ |
|||
namespace LINGYUN.Linq.Dynamic.Queryable; |
|||
public enum DynamicComparison |
|||
{ |
|||
/// <summary>
|
|||
/// 等于
|
|||
/// </summary>
|
|||
Equal = 0, |
|||
/// <summary>
|
|||
/// 不等于
|
|||
/// </summary>
|
|||
NotEqual = 1, |
|||
/// <summary>
|
|||
/// 小于
|
|||
/// </summary>
|
|||
LessThan = 2, |
|||
/// <summary>
|
|||
/// 小于等于
|
|||
/// </summary>
|
|||
LessThanOrEqual = 3, |
|||
/// <summary>
|
|||
/// 大于
|
|||
/// </summary>
|
|||
GreaterThan = 4, |
|||
/// <summary>
|
|||
/// 大于等于
|
|||
/// </summary>
|
|||
GreaterThanOrEqual = 5, |
|||
/// <summary>
|
|||
/// 左包含
|
|||
/// </summary>
|
|||
StartsWith = 6, |
|||
/// <summary>
|
|||
/// 左不包含
|
|||
/// </summary>
|
|||
NotStartsWith = 7, |
|||
/// <summary>
|
|||
/// 右包含
|
|||
/// </summary>
|
|||
EndsWith = 8, |
|||
/// <summary>
|
|||
/// 右不包含
|
|||
/// </summary>
|
|||
NotEndsWith = 9, |
|||
/// <summary>
|
|||
/// 包含
|
|||
/// </summary>
|
|||
Contains = 10, |
|||
/// <summary>
|
|||
/// 不包含
|
|||
/// </summary>
|
|||
NotContains = 11 |
|||
} |
|||
|
|||
@ -0,0 +1,13 @@ |
|||
namespace LINGYUN.Linq.Dynamic.Queryable; |
|||
|
|||
public enum DynamicLogic |
|||
{ |
|||
/// <summary>
|
|||
/// 且
|
|||
/// </summary>
|
|||
And = 0, |
|||
/// <summary>
|
|||
/// 或
|
|||
/// </summary>
|
|||
Or = 1 |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
namespace LINGYUN.Linq.Dynamic.Queryable; |
|||
|
|||
public class DynamicParamter |
|||
{ |
|||
public string Filed { get; set; } |
|||
|
|||
public DynamicLogic Logic { get; set; } = DynamicLogic.And; |
|||
|
|||
public DynamicComparison Comparison { get; set; } = DynamicComparison.Equal; |
|||
|
|||
public object Value { get; set; } |
|||
public string Type { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Linq.Dynamic.Queryable; |
|||
|
|||
public class DynamicQueryable |
|||
{ |
|||
public List<DynamicParamter> Paramters { get; set; } = new List<DynamicParamter>(); |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
# LINGYUN.Linq.Dynamic.Queryable |
|||
|
|||
动态查询基本库, 扩展Linq, 动态构建表达式树 |
|||
|
|||
## 配置使用 |
|||
|
|||
模块按需引用, 只提供针对Linq的扩展 |
|||
|
|||
```csharp |
|||
|
|||
``` |
|||
|
|||
@ -0,0 +1,119 @@ |
|||
using LINGYUN.Linq.Dynamic.Queryable; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace System.Linq.Expressions; |
|||
|
|||
public static class ObjectQueryableExtensions |
|||
{ |
|||
public static Expression<T> DynamicQuery<T>( |
|||
this Expression<T> condition, |
|||
DynamicQueryable queryable) |
|||
{ |
|||
var typeExpression = condition.Parameters.FirstOrDefault(); |
|||
|
|||
return BuildExpressions(condition, typeExpression, queryable.Paramters); |
|||
} |
|||
|
|||
private static Expression<T> BuildExpressions<T>( |
|||
Expression<T> condition, |
|||
Expression typeExpression, |
|||
List<DynamicParamter> paramters) |
|||
{ |
|||
var expressions = new Stack<Expression>(); |
|||
foreach (var paramter in paramters) |
|||
{ |
|||
Expression exp = null; |
|||
Type propertyType = null; |
|||
var leftParamter = Expression.PropertyOrField(typeExpression, paramter.Filed); |
|||
if (!string.IsNullOrWhiteSpace(paramter.Type)) |
|||
{ |
|||
propertyType = Type.GetType(paramter.Type, true); |
|||
} |
|||
else |
|||
{ |
|||
propertyType = (leftParamter.Member as PropertyInfo)?.PropertyType ?? paramter.Value.GetType(); |
|||
} |
|||
var rightParamter = Expression.Convert(Expression.Constant(paramter.Value), propertyType); |
|||
switch (paramter.Comparison) |
|||
{ |
|||
case DynamicComparison.Equal: |
|||
exp = Expression.Equal(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.NotEqual: |
|||
exp = Expression.NotEqual(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.LessThan: |
|||
exp = Expression.LessThan(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.LessThanOrEqual: |
|||
exp = Expression.LessThanOrEqual(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.GreaterThan: |
|||
exp = Expression.GreaterThan(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.GreaterThanOrEqual: |
|||
exp = Expression.GreaterThanOrEqual(leftParamter, rightParamter); |
|||
break; |
|||
case DynamicComparison.StartsWith: |
|||
exp = Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }), |
|||
rightParamter); |
|||
break; |
|||
case DynamicComparison.NotStartsWith: |
|||
exp = Expression.Not( |
|||
Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }), |
|||
rightParamter)); |
|||
break; |
|||
case DynamicComparison.EndsWith: |
|||
exp = Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }), |
|||
rightParamter); |
|||
break; |
|||
case DynamicComparison.NotEndsWith: |
|||
exp = Expression.Not( |
|||
Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }), |
|||
rightParamter)); |
|||
break; |
|||
case DynamicComparison.Contains: |
|||
exp = Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }), |
|||
rightParamter); |
|||
break; |
|||
case DynamicComparison.NotContains: |
|||
exp = Expression.Not( |
|||
Expression.Call( |
|||
leftParamter, |
|||
typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }), |
|||
rightParamter)); |
|||
break; |
|||
} |
|||
expressions.Push(exp); |
|||
|
|||
while (expressions.Count > 1) |
|||
{ |
|||
var exp1 = expressions.Pop(); |
|||
var exp2 = expressions.Pop(); |
|||
|
|||
switch (paramter.Logic) |
|||
{ |
|||
case DynamicLogic.And: |
|||
expressions.Push(Expression.AndAlso(exp1, exp2)); |
|||
break; |
|||
case DynamicLogic.Or: |
|||
expressions.Push(Expression.Or(exp1, exp2)); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return Expression.Lambda<T>(expressions.Pop(), condition.Parameters.ToArray()); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
# Dynamic.Queryable |
|||
|
|||
动态查询支持库, 为以后台服务提供动态查询支持 |
|||
|
|||
* 应用程序接口定义层引用**LINGYUN.Abp.Dynamic.Queryable.Application.Contracts**模块, 实现**IDynamicQueryableAppService**接口可对外提供动态查询支持 |
|||
|
|||
* 应用程序接口实现层引用**LINGYUN.Abp.Dynamic.Queryable.Application**模块,继承自**DynamicQueryableAppService**接口,实现**GetCountAsync**与**GetListAsync**方法即可(为仓储层接口提供传递的**Expression<Func<TEntity, bool>>**结构) |
|||
|
|||
* 控制器层引用**LINGYUN.Abp.Dynamic.Queryable.HttpApi**模块,继承**DynamicQueryableControllerBase**接口,自动公开动态查询接口。 |
|||
|
|||
## 接口说明 |
|||
|
|||
* **GetAvailableFieldsAsync**(<font color="green">[GET]</font> <font color="blue">/{controller}/available-fields</font>): 对外提供可选的属性明细, 默认返回所有字段(不包含已定义的排除字段). |
|||
|
|||
* **GetListAsync**(<font color="orange">[POST]</font> <font color="blue">/{controller}/search</font>): 根据用户传递的动态条件返回查询结果列表. |
|||
|
|||
## 配置使用 |
|||
|
|||
* AbpDynamicQueryableOptions.IgnoreFields: 定义不对用户公开的字段列表,默认排除租户标识、软删除过滤器接口字段. |
|||
|
|||
Loading…
Reference in new issue