开发者

IRouteConstraint for enum

I want to create an IRouteConstraint that filters a value against possibl开发者_运维技巧e values of an enum. I tried to google it for myself, but that didn't result in anything.

Any ideas?


This is what I came up with:

public class EnumRouteConstraint<T> : IRouteConstraint
  where T : struct
{

  private readonly HashSet<string> enumNames;

  public EnumRouteConstraint()
  {
    string[] names = Enum.GetNames(typeof(T));
    enumNames = new HashSet<string>(from name in names select name.ToLowerInvariant());
  }

  public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
  {
    return enumNames.Contains(values[parameterName].ToString().ToLowerInvariant());
  }
}

I think a HashSet will perform much better than Enum.GetNames on each Match. Also the use generics makes it look a bit more fluent when you use the constraint.

Unfortunately, where T : Enum is not allowed by the compiler.


See this

Essentially, you need

  private Type enumType;

  public EnumConstraint(Type enumType)
  {
    this.enumType = enumType;
  }

  public bool Match(HttpContextBase httpContext, 
    Route route, 
    string parameterName,     
    RouteValueDictionary values, 
    RouteDirection routeDirection)
  {
    // You can also try Enum.IsDefined, but docs say nothing as to
    // is it case sensitive or not.
    return Enum.GetNames(enumType).Any(s => s.ToLowerInvariant() == values[parameterName].ToString());
  }


----------------- 2022 Update -----------------

Try to use a generic RouteConstraint


builder.Services.Configure<RouteOptions>(routeOptions =>
{
    routeOptions.ConstraintMap.Add(nameof(Status) , typeof(EnumConstraint<Status>));
});


public class EnumConstraint<TEnum> : IRouteConstraint
        where TEnum : struct, IConvertible
{
    bool IRouteConstraint.Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (httpContext == null)
            throw new ArgumentNullException(nameof(httpContext));

        if (route == null)
            throw new ArgumentNullException(nameof(route));

        if (routeKey == null)
            throw new ArgumentNullException(nameof(routeKey));

        if (values == null)
            throw new ArgumentNullException(nameof(values));

        if (values.TryGetValue(routeKey, out var routeValue))
        {
            if(!typeof(TEnum).IsEnum)
                throw new ArgumentException($"{nameof(TEnum)} is not enum!");
            var parameterValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
            if (parameterValueString is null)
                return false;
            EnumConverter enumConverter = new (typeof(TEnum));
            if (enumConverter.ConvertFromString(parameterValueString) is not null)
                return true;
        }
        return false;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜