mirror of https://github.com/abpframework/abp.git
21 changed files with 713 additions and 11 deletions
@ -0,0 +1,275 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
using Microsoft.AspNetCore.Mvc.Internal; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Http; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpAppServiceConvention : IApplicationModelConvention |
|||
{ |
|||
private readonly Lazy<AbpAspNetCoreMvcOptions> _configuration; |
|||
|
|||
public AbpAppServiceConvention(IServiceCollection services) |
|||
{ |
|||
_configuration = new Lazy<AbpAspNetCoreMvcOptions>(() => |
|||
{ |
|||
return services |
|||
.GetSingletonInstance<IAbpApplication>() |
|||
.ServiceProvider |
|||
.GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>() |
|||
.Value; |
|||
}, true); |
|||
} |
|||
|
|||
public void Apply(ApplicationModel application) |
|||
{ |
|||
foreach (var controller in application.Controllers) |
|||
{ |
|||
var type = controller.ControllerType.AsType(); |
|||
var configuration = GetControllerSettingOrNull(type); |
|||
|
|||
if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(type)) |
|||
{ |
|||
controller.ControllerName = controller.ControllerName.RemovePostFix(ApplicationService.CommonPostfixes); |
|||
configuration?.ControllerModelConfigurer(controller); |
|||
|
|||
ConfigureArea(controller, configuration); |
|||
ConfigureRemoteService(controller, configuration); |
|||
} |
|||
else |
|||
{ |
|||
var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(type.GetTypeInfo()); |
|||
if (remoteServiceAtt != null && remoteServiceAtt.IsEnabledFor(type)) |
|||
{ |
|||
ConfigureRemoteService(controller, configuration); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void ConfigureArea(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (controller.RouteValues.ContainsKey("area")) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
controller.RouteValues["area"] = configuration.ModuleName; |
|||
} |
|||
|
|||
private void ConfigureRemoteService(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) |
|||
{ |
|||
ConfigureApiExplorer(controller); |
|||
ConfigureSelector(controller, configuration); |
|||
ConfigureParameters(controller); |
|||
} |
|||
|
|||
private void ConfigureParameters(ControllerModel controller) |
|||
{ |
|||
foreach (var action in controller.Actions) |
|||
{ |
|||
foreach (var prm in action.Parameters) |
|||
{ |
|||
if (prm.BindingInfo != null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (!TypeHelper.IsPrimitiveExtendedIncludingNullable(prm.ParameterInfo.ParameterType)) |
|||
{ |
|||
if (CanUseFormBodyBinding(action, prm)) |
|||
{ |
|||
prm.BindingInfo = BindingInfo.GetBindingInfo(new[] { new FromBodyAttribute() }); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private bool CanUseFormBodyBinding(ActionModel action, ParameterModel parameter) |
|||
{ |
|||
if (_configuration.Value.FormBodyBindingIgnoredTypes.Any(t => t.IsAssignableFrom(parameter.ParameterInfo.ParameterType))) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
foreach (var selector in action.Selectors) |
|||
{ |
|||
if (selector.ActionConstraints == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
foreach (var actionConstraint in selector.ActionConstraints) |
|||
{ |
|||
var httpMethodActionConstraint = actionConstraint as HttpMethodActionConstraint; |
|||
if (httpMethodActionConstraint == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (httpMethodActionConstraint.HttpMethods.All(hm => hm.IsIn("GET", "DELETE", "TRACE", "HEAD"))) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void ConfigureApiExplorer(ControllerModel controller) |
|||
{ |
|||
if (controller.ApiExplorer.GroupName.IsNullOrEmpty()) |
|||
{ |
|||
controller.ApiExplorer.GroupName = controller.ControllerName; |
|||
} |
|||
|
|||
if (controller.ApiExplorer.IsVisible == null) |
|||
{ |
|||
var controllerType = controller.ControllerType.AsType(); |
|||
var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(controllerType.GetTypeInfo()); |
|||
if (remoteServiceAtt != null) |
|||
{ |
|||
controller.ApiExplorer.IsVisible = |
|||
remoteServiceAtt.IsEnabledFor(controllerType) && |
|||
remoteServiceAtt.IsMetadataEnabledFor(controllerType); |
|||
} |
|||
else |
|||
{ |
|||
controller.ApiExplorer.IsVisible = true; |
|||
} |
|||
} |
|||
|
|||
foreach (var action in controller.Actions) |
|||
{ |
|||
ConfigureApiExplorer(action); |
|||
} |
|||
} |
|||
|
|||
private void ConfigureApiExplorer(ActionModel action) |
|||
{ |
|||
if (action.ApiExplorer.IsVisible == null) |
|||
{ |
|||
var remoteServiceAtt = ReflectionHelper.GetSingleAttributeOrDefault<RemoteServiceAttribute>(action.ActionMethod); |
|||
if (remoteServiceAtt != null) |
|||
{ |
|||
action.ApiExplorer.IsVisible = |
|||
remoteServiceAtt.IsEnabledFor(action.ActionMethod) && |
|||
remoteServiceAtt.IsMetadataEnabledFor(action.ActionMethod); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void ConfigureSelector(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) |
|||
{ |
|||
RemoveEmptySelectors(controller.Selectors); |
|||
|
|||
if (controller.Selectors.Any(selector => selector.AttributeRouteModel != null)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var moduleName = GetModuleNameOrDefault(controller.ControllerType.AsType()); |
|||
|
|||
foreach (var action in controller.Actions) |
|||
{ |
|||
ConfigureSelector(moduleName, controller.ControllerName, action, configuration); |
|||
} |
|||
} |
|||
|
|||
private void ConfigureSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) |
|||
{ |
|||
RemoveEmptySelectors(action.Selectors); |
|||
|
|||
if (!action.Selectors.Any()) |
|||
{ |
|||
AddAbpServiceSelector(moduleName, controllerName, action, configuration); |
|||
} |
|||
else |
|||
{ |
|||
NormalizeSelectorRoutes(moduleName, controllerName, action); |
|||
} |
|||
} |
|||
|
|||
private void AddAbpServiceSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) |
|||
{ |
|||
var abpServiceSelectorModel = new SelectorModel |
|||
{ |
|||
AttributeRouteModel = CreateAbpServiceAttributeRouteModel(moduleName, controllerName, action) |
|||
}; |
|||
|
|||
var verb = configuration?.UseConventionalHttpVerbs == true |
|||
? HttpVerbHelper.GetConventionalVerbForMethodName(action.ActionName) |
|||
: HttpVerbHelper.DefaultHttpVerb; |
|||
|
|||
abpServiceSelectorModel.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { verb })); |
|||
|
|||
action.Selectors.Add(abpServiceSelectorModel); |
|||
} |
|||
|
|||
private static void NormalizeSelectorRoutes(string moduleName, string controllerName, ActionModel action) |
|||
{ |
|||
foreach (var selector in action.Selectors) |
|||
{ |
|||
if (selector.AttributeRouteModel == null) |
|||
{ |
|||
selector.AttributeRouteModel = CreateAbpServiceAttributeRouteModel( |
|||
moduleName, |
|||
controllerName, |
|||
action |
|||
); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private string GetModuleNameOrDefault(Type controllerType) |
|||
{ |
|||
return GetControllerSettingOrNull(controllerType)?.ModuleName ?? |
|||
AbpControllerAssemblySetting.DefaultServiceModuleName; |
|||
} |
|||
|
|||
[CanBeNull] |
|||
private AbpControllerAssemblySetting GetControllerSettingOrNull(Type controllerType) |
|||
{ |
|||
return _configuration.Value.ControllerAssemblySettings.GetSettingOrNull(controllerType); |
|||
} |
|||
|
|||
private static AttributeRouteModel CreateAbpServiceAttributeRouteModel(string moduleName, string controllerName, ActionModel action) |
|||
{ |
|||
return new AttributeRouteModel( |
|||
new RouteAttribute( |
|||
$"api/services/{moduleName}/{controllerName}/{action.ActionName}" |
|||
) |
|||
); |
|||
} |
|||
|
|||
private static void RemoveEmptySelectors(IList<SelectorModel> selectors) |
|||
{ |
|||
selectors |
|||
.Where(IsEmptySelector) |
|||
.ToList() |
|||
.ForEach(s => selectors.Remove(s)); |
|||
} |
|||
|
|||
private static bool IsEmptySelector(SelectorModel selector) |
|||
{ |
|||
return selector.AttributeRouteModel == null && selector.ActionConstraints.IsNullOrEmpty(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using Microsoft.AspNetCore.Http; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpAspNetCoreMvcOptions |
|||
{ |
|||
//TODO: Group into a class since they are related.
|
|||
public ControllerAssemblySettingList ControllerAssemblySettings { get; } |
|||
public List<Type> FormBodyBindingIgnoredTypes { get; } |
|||
|
|||
public AbpAspNetCoreMvcOptions() |
|||
{ |
|||
FormBodyBindingIgnoredTypes = new List<Type> |
|||
{ |
|||
typeof(IFormFile) |
|||
}; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder CreateControllersForAppServices( |
|||
Assembly assembly, |
|||
string moduleName = AbpControllerAssemblySetting.DefaultServiceModuleName, |
|||
bool useConventionalHttpVerbs = true) |
|||
{ |
|||
var setting = new AbpControllerAssemblySetting(moduleName, assembly, useConventionalHttpVerbs); |
|||
ControllerAssemblySettings.Add(setting); |
|||
return new AbpControllerAssemblySettingBuilder(setting); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpControllerAssemblySetting |
|||
{ |
|||
/// <summary>
|
|||
/// "app".
|
|||
/// </summary>
|
|||
public const string DefaultServiceModuleName = "app"; |
|||
|
|||
public string ModuleName { get; } |
|||
|
|||
public Assembly Assembly { get; } |
|||
|
|||
public bool UseConventionalHttpVerbs { get; } |
|||
|
|||
public Func<Type, bool> TypePredicate { get; set; } |
|||
|
|||
public Action<ControllerModel> ControllerModelConfigurer { get; set; } |
|||
|
|||
public AbpControllerAssemblySetting(string moduleName, Assembly assembly, bool useConventionalHttpVerbs) |
|||
{ |
|||
ModuleName = moduleName; |
|||
Assembly = assembly; |
|||
UseConventionalHttpVerbs = useConventionalHttpVerbs; |
|||
|
|||
TypePredicate = type => true; |
|||
ControllerModelConfigurer = controller => { }; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpControllerAssemblySettingBuilder : IAbpControllerAssemblySettingBuilder |
|||
{ |
|||
private readonly AbpControllerAssemblySetting _setting; |
|||
|
|||
public AbpControllerAssemblySettingBuilder(AbpControllerAssemblySetting setting) |
|||
{ |
|||
_setting = setting; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder Where(Func<Type, bool> predicate) |
|||
{ |
|||
_setting.TypePredicate = predicate; |
|||
return this; |
|||
} |
|||
|
|||
public AbpControllerAssemblySettingBuilder ConfigureControllerModel(Action<ControllerModel> configurer) |
|||
{ |
|||
_setting.ControllerModelConfigurer = configurer; |
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
internal static class AbpMvcOptionsExtensions |
|||
{ |
|||
public static void AddAbp(this MvcOptions options, IServiceCollection services) |
|||
{ |
|||
AddConventions(options, services); |
|||
AddFilters(options); |
|||
AddModelBinders(options); |
|||
} |
|||
|
|||
private static void AddConventions(MvcOptions options, IServiceCollection services) |
|||
{ |
|||
options.Conventions.Add(new AbpAppServiceConvention(services)); |
|||
} |
|||
|
|||
private static void AddFilters(MvcOptions options) |
|||
{ |
|||
//options.Filters.AddService(typeof(AbpAuthorizationFilter));
|
|||
//options.Filters.AddService(typeof(AbpAuditActionFilter));
|
|||
//options.Filters.AddService(typeof(AbpValidationActionFilter));
|
|||
//options.Filters.AddService(typeof(AbpUowActionFilter));
|
|||
//options.Filters.AddService(typeof(AbpExceptionFilter));
|
|||
//options.Filters.AddService(typeof(AbpResultFilter));
|
|||
} |
|||
|
|||
private static void AddModelBinders(MvcOptions options) |
|||
{ |
|||
//options.ModelBinderProviders.Add(new AbpDateTimeModelBinderProvider());
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class ControllerAssemblySettingList : List<AbpControllerAssemblySetting> |
|||
{ |
|||
[CanBeNull] |
|||
public AbpControllerAssemblySetting GetSettingOrNull(Type controllerType) |
|||
{ |
|||
return this.FirstOrDefault(controllerSetting => controllerSetting.Assembly == controllerType.GetAssembly()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationModels; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public interface IAbpControllerAssemblySettingBuilder |
|||
{ |
|||
AbpControllerAssemblySettingBuilder Where(Func<Type, bool> predicate); |
|||
|
|||
AbpControllerAssemblySettingBuilder ConfigureControllerModel(Action<ControllerModel> configurer); |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
using System.Linq; |
|||
|
|||
namespace System.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// Extensions to <see cref="MemberInfo"/>.
|
|||
/// </summary>
|
|||
public static class AbpMemberInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets a single attribute for a member.
|
|||
/// </summary>
|
|||
/// <typeparam name="TAttribute">Type of the attribute</typeparam>
|
|||
/// <param name="memberInfo">The member that will be checked for the attribute</param>
|
|||
/// <param name="inherit">Include inherited attributes</param>
|
|||
/// <returns>Returns the attribute object if found. Returns null if not found.</returns>
|
|||
public static TAttribute GetSingleAttributeOrNull<TAttribute>(this MemberInfo memberInfo, bool inherit = true) |
|||
where TAttribute : Attribute |
|||
{ |
|||
if (memberInfo == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(memberInfo)); |
|||
} |
|||
|
|||
var attrs = memberInfo.GetCustomAttributes(typeof(TAttribute), inherit).ToArray(); |
|||
if (attrs.Length > 0) |
|||
{ |
|||
return (TAttribute)attrs[0]; |
|||
} |
|||
|
|||
return default(TAttribute); |
|||
} |
|||
|
|||
|
|||
public static TAttribute GetSingleAttributeOfTypeOrBaseTypesOrNull<TAttribute>(this Type type, bool inherit = true) |
|||
where TAttribute : Attribute |
|||
{ |
|||
var attr = type.GetTypeInfo().GetSingleAttributeOrNull<TAttribute>(); |
|||
if (attr != null) |
|||
{ |
|||
return attr; |
|||
} |
|||
|
|||
if (type.GetTypeInfo().BaseType == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return type.GetTypeInfo().BaseType.GetSingleAttributeOfTypeOrBaseTypesOrNull<TAttribute>(inherit); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.Http |
|||
{ |
|||
public class HttpVerbHelper //TODO: Internal?
|
|||
{ |
|||
public const string DefaultHttpVerb = "POST"; |
|||
|
|||
public static string GetConventionalVerbForMethodName(string methodName) |
|||
{ |
|||
if (methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "GET"; |
|||
} |
|||
|
|||
if (methodName.StartsWith("Put", StringComparison.OrdinalIgnoreCase) || |
|||
methodName.StartsWith("Update", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "PUT"; |
|||
} |
|||
|
|||
if (methodName.StartsWith("Delete", StringComparison.OrdinalIgnoreCase) || |
|||
methodName.StartsWith("Remove", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "DELETE"; |
|||
} |
|||
|
|||
if (methodName.StartsWith("Patch", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "PATCH"; |
|||
} |
|||
|
|||
if (methodName.StartsWith("Post", StringComparison.OrdinalIgnoreCase) || |
|||
methodName.StartsWith("Create", StringComparison.OrdinalIgnoreCase) || |
|||
methodName.StartsWith("Insert", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return "POST"; |
|||
} |
|||
|
|||
//Default
|
|||
return DefaultHttpVerb; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.Http |
|||
{ |
|||
[Serializable] |
|||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Method)] |
|||
public class RemoteServiceAttribute : Attribute |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsMetadataEnabled { get; set; } |
|||
|
|||
public RemoteServiceAttribute(bool isEnabled = true) |
|||
{ |
|||
IsEnabled = isEnabled; |
|||
IsMetadataEnabled = true; |
|||
} |
|||
|
|||
public virtual bool IsEnabledFor(Type type) |
|||
{ |
|||
return IsEnabled; |
|||
} |
|||
|
|||
public virtual bool IsEnabledFor(MethodInfo method) |
|||
{ |
|||
return IsEnabled; |
|||
} |
|||
|
|||
public virtual bool IsMetadataEnabledFor(Type type) |
|||
{ |
|||
return IsMetadataEnabled; |
|||
} |
|||
|
|||
public virtual bool IsMetadataEnabledFor(MethodInfo method) |
|||
{ |
|||
return IsMetadataEnabled; |
|||
} |
|||
|
|||
public static bool IsExplicitlyEnabledFor(Type type) |
|||
{ |
|||
var remoteServiceAttr = type.GetTypeInfo().GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && remoteServiceAttr.IsEnabledFor(type); |
|||
} |
|||
|
|||
public static bool IsExplicitlyDisabledFor(Type type) |
|||
{ |
|||
var remoteServiceAttr = type.GetTypeInfo().GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && !remoteServiceAttr.IsEnabledFor(type); |
|||
} |
|||
|
|||
public static bool IsMetadataExplicitlyEnabledFor(Type type) |
|||
{ |
|||
var remoteServiceAttr = type.GetTypeInfo().GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && remoteServiceAttr.IsMetadataEnabledFor(type); |
|||
} |
|||
|
|||
public static bool IsMetadataExplicitlyDisabledFor(Type type) |
|||
{ |
|||
var remoteServiceAttr = type.GetTypeInfo().GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && !remoteServiceAttr.IsMetadataEnabledFor(type); |
|||
} |
|||
|
|||
public static bool IsMetadataExplicitlyDisabledFor(MethodInfo method) |
|||
{ |
|||
var remoteServiceAttr = method.GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && !remoteServiceAttr.IsMetadataEnabledFor(method); |
|||
} |
|||
|
|||
public static bool IsMetadataExplicitlyEnabledFor(MethodInfo method) |
|||
{ |
|||
var remoteServiceAttr = method.GetSingleAttributeOrNull<RemoteServiceAttribute>(); |
|||
return remoteServiceAttr != null && remoteServiceAttr.IsMetadataEnabledFor(method); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// Some simple type-checking methods used internally.
|
|||
/// </summary>
|
|||
public static class TypeHelper |
|||
{ |
|||
public static bool IsFunc(object obj) |
|||
{ |
|||
if (obj == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var type = obj.GetType(); |
|||
if (!type.GetTypeInfo().IsGenericType) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return type.GetGenericTypeDefinition() == typeof(Func<>); |
|||
} |
|||
|
|||
public static bool IsFunc<TReturn>(object obj) |
|||
{ |
|||
return obj != null && obj.GetType() == typeof(Func<TReturn>); |
|||
} |
|||
|
|||
public static bool IsPrimitiveExtendedIncludingNullable(Type type, bool includeEnums = false) |
|||
{ |
|||
if (IsPrimitiveExtended(type, includeEnums)) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) |
|||
{ |
|||
return IsPrimitiveExtended(type.GenericTypeArguments[0], includeEnums); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
private static bool IsPrimitiveExtended(Type type, bool includeEnums) |
|||
{ |
|||
if (type.GetTypeInfo().IsPrimitive) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
if (includeEnums && type.GetTypeInfo().IsEnum) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return type == typeof (string) || |
|||
type == typeof (decimal) || |
|||
type == typeof (DateTime) || |
|||
type == typeof (DateTimeOffset) || |
|||
type == typeof (TimeSpan) || |
|||
type == typeof (Guid); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue