C# 扩展方法在 ASP.Net 项目中派上用场

作者:微信公众号:【架构师老卢】
2-14 9:43
19

概述:在 C# 和 ASP.NET 开发领域,扩展方法作为宝贵的工具,使开发人员能够增强其代码的表现力和效率。在这篇博文中,我们将深入探讨任何 ASP.Net Core 项目都需要的一些基本扩展方法,这些方法可以提升您的 Web 开发项目。HTTPContext 扩展获取基本路径public static string GetBasePath(this HttpContext httpContext) {  return $”{httpContext.Request.Scheme}://{httpContext.Request.Host}”; }检查请求标头是否具有特定键public stat

在 C# 和 ASP.NET 开发领域,扩展方法作为宝贵的工具,使开发人员能够增强其代码的表现力和效率。在这篇博文中,我们将深入探讨任何 ASP.Net Core 项目都需要的一些基本扩展方法,这些方法可以提升您的 Web 开发项目。

HTTPContext 扩展

获取基本路径

public static string GetBasePath(this HttpContext httpContext)  
{  
 return $”{httpContext.Request.Scheme}://{httpContext.Request.Host}”;  
}

检查请求标头是否具有特定键

public static bool HasRequestHeader(this HttpContext httpContext, string headerName)  
{  
 return httpContext.Request.Headers.ContainsKey(headerName);  
}

检查响应标头是否具有特定键

public static bool HasResponseHeader(this HttpContext httpContext, string headerName)  
{  
 return httpContext.Response.Headers.ContainsKey(headerName);  
}

检查请求标头键是否具有所需的值

public static bool HasRequestHeaderValue(this HttpContext httpContext, string headerName, string headerValue)  
{  
 return httpContext.Request.Headers.TryGetValue(headerName, out var header)  
 && header.Any(a => a.Equals(headerValue, StringComparison.OrdinalIgnoreCase));  
}

检查响应标头键是否具有所需的值

public static bool HasResponseHeaderValue(this HttpContext httpContext, string headerName, string headerValue)  
{  
 return httpContext.Response.Headers.TryGetValue(headerName, out var header)  
 && header.Any(a => a.Equals(headerValue, StringComparison.OrdinalIgnoreCase));  
}

IEnumerable 扩展

将任何 IEnumerable 转换为 CSV 字符串

public static string ConvertToCSVString<T>(this IEnumerable<T> items)  
{  
    if (items.Any())  
    {  
        var lines = new List<string>();  
        var header = string.Empty;  
  
        if (items.FirstOrDefault().GetType() == typeof(JObject))  
        {  
            var jObject = (JObject)Convert.ChangeType(items.FirstOrDefault(), typeof(JObject));  
  
            header = string.Join(",", jObject.Properties().Select(x => x.Name));  
  
            lines.Add(header);  
  
            **///**/DO NOT include the starting and ending quotes inside the $ string interpolation.  
            var valueLines = items.Select(row =>  
                                    string.Join(",", header.Split(',')  
                                        .Select(a => "\\"" + $"{((JObject)Convert.ChangeType(row, typeof(JObject))).GetValue(a)}"?  
                                                        .Replace(Environment.NewLine, string.Empty, StringComparison.OrdinalIgnoreCase)  
                                                        .Replace("\\"", "\\"\\"", StringComparison.OrdinalIgnoreCase)  
                                                        + "\\""  
                                                        )));  
  
            lines.AddRange(valueLines);  
        }  
        else  
        {  
            var props = items.FirstOrDefault().GetType().GetProperties();  
  
            header = string.Join(",", props.Select(x => x.Name));  
  
            lines.Add(header);  
  
            //DO NOT include the starting and ending quotes inside the $ string interpolation.  
            var valueLines = items.Select(row =>  
                                    string.Join(",", header.Split(',')  
                                        .Select(a => "\\"" + $"{row.GetType().GetProperty(a).GetValue(row, null)}"?  
                                                        .Replace(Environment.NewLine, string.Empty, StringComparison.OrdinalIgnoreCase)  
                                                        .Replace("\\"", "\\"\\"", StringComparison.OrdinalIgnoreCase)  
                                                        + "\\""  
                                                        )));  
  
            lines.AddRange(valueLines);  
        }  
  
        var csvString = string.Join("\\r\\n", lines.ToArray());  
  
        return csvString;  
    }  
    else  
    {  
        return string.Empty;  
    }  
}

将任何 IEnumerable 转换为 DataTable

public static DataTable ToDataTable<T>(this IEnumerable<T> items)  
{  
    DataTable dataTable = new DataTable(typeof(T).Name);  
  
    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);  
    foreach (PropertyInfo prop in Props)  
    {  
        dataTable.Columns.Add(prop.Name);  
    }  
    foreach (T item in items)  
    {  
        var values = new object[Props.Length];  
        for (int i = 0; i < Props.Length; i++)  
        {  
            values[i] = Props[i].GetValue(item, null);  
        }  
        dataTable.Rows.Add(values);  
    }  
  
    return dataTable;  
}

会话扩展

替换会话密钥中的值

public static void Replace(this ISession session, string key, object data)  
{  
    if (session.Keys.Any(x => x.Equals(key, StringComparison.OrdinalIgnoreCase)))  
    {  
        session.Remove(key);  
    }  
  
    session.SetString(key, JsonConvert.SerializeObject(data));  
}

从会话密钥中获取价值

public static bool TryGet<T>(this ISession session, string key, out T data, bool removeKey = false)  
{  
    if (session.Keys.Any(x => x.Equals(key, StringComparison.OrdinalIgnoreCase)))  
    {  
        var objString = session.GetString(key);  
  
        data = JsonConvert.DeserializeObject<T>(objString);  
  
        if (removeKey)  
        {  
            session.Remove(key);  
        }  
  
        return true;  
    }  
  
    data = default;  
    return false;  
}

ClaimsPrincipal 扩展

检查声明是否具有特定角色

public static bool HasRole(this ClaimsPrincipal principal, string role)  
{  
 return principal.HasClaim(c =>  
 c.Type == ClaimTypes.Role &&  
 c.Value.Equals(role, StringComparison.OrdinalIgnoreCase));  
}

从声明中获取角色

public static IEnumerable<string> GetRoles(this ClaimsPrincipal principal)  
{  
 return principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(s => s.Value);  
}

从索赔中获取特定索赔

public static T GetClaim<T>(this ClaimsPrincipal principal, string claim)  
 {  
 var result = principal?.Claims?.FirstOrDefault(f => f.Type.Equals(claim, StringComparison.OrdinalIgnoreCase))?.Value;  
return (T)Convert.ChangeType(result, typeof(T));  
 }

DateTime 扩展

转换为其他时区

public static DateTime ConvertToTimeZone(this DateTime dateTime, string timeZoneId)  
{  
 return TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZoneInfo.FindSystemTimeZoneById(timeZoneId));  
}

检查给定的 DateTime 是否在时间范围之间

public static bool IsBetweenTimeRange(this DateTime comparisonTime, DateTime? startDate, DateTime? endDate)  
{  
 return (startDate.HasValue ? comparisonTime >= startDate.Value : true) && (endDate.HasValue ? comparisonTime \<= endDate.Value : true);  
}

检查给定的 DateTimeOffset 是否在时间范围之间

public static bool IsBetweenTimeRange(this DateTime comparisonTime, DateTimeOffset? startDate, DateTimeOffset? endDate)  
{  
 return comparisonTime.IsBetweenTimeRange(startDate.HasValue ? startDate.Value.DateTime : null, endDate.HasValue ? endDate.Value.DateTime : null);  
}

转换为基于 TimeZone 的 DateTimeOffset

public static DateTimeOffset? ToDateTimeOffset(this DateTime? dateTime, string timeZoneId)  
{  
 return dateTime.HasValue ? new DateTimeOffset(dateTime.Value, TimeZoneInfo.FindSystemTimeZoneById(timeZoneId).BaseUtcOffset) : null;  
}

枚举扩展

获取枚举的显示名称

public static string GetDisplayName(this Enum enumValue)  
{  
 var displayName = enumValue.GetType().GetMember(enumValue.ToString()).FirstOrDefault().GetCustomAttribute<DisplayAttribute>()?.GetName();  
return string.IsNullOrWhiteSpace(displayName) ? enumValue.ToString() : displayName;  
}

HTTPResponseMessage 扩展

确保 HTTPResponseMessage 具有成功状态代码并记录失败

public static async Task EnsureSuccessStatusCodeAndLogFailures(this HttpResponseMessage httpResponseMessage, ILogger logger)  
{  
    if (httpResponseMessage == null)  
    {  
        throw new ArgumentNullException(nameof(httpResponseMessage));  
    }  
    if (logger == null)  
    {  
        throw new ArgumentNullException(nameof(logger));  
    }  
  
    if (!httpResponseMessage.IsSuccessStatusCode)  
    {  
        var response = await httpResponseMessage.Content?.ReadAsStringAsync();  
  
        var requestUri = httpResponseMessage.RequestMessage?.RequestUri;  
  
        logger.LogError($"HTTP call to {requestUri} returned status code {httpResponseMessage.StatusCode} with response {response}");  
    }  
  
    httpResponseMessage.EnsureSuccessStatusCode();  
}

TokenResponse 扩展

确保 TokenResponse 具有成功状态并记录失败

public static void CheckResponseAndLogFailures(this TokenResponse tokenResponse, ILogger logger)  
{  
    if (tokenResponse == null)  
    {  
        throw new ArgumentNullException(nameof(tokenResponse));  
    }  
    if (logger == null)  
    {  
        throw new ArgumentNullException(nameof(logger));  
    }  
  
    if (tokenResponse.IsError)  
    {  
        var response = JsonConvert.SerializeObject(tokenResponse);  
  
        logger.LogError("Access Token call to returned with error and data: {data}", response);  
    }  
}

字符串扩展

public static string Slugify(this string phrase)  
{  
    if (string.IsNullOrWhiteSpace(phrase))  
    {  
        return string.Empty;  
    }  
  
    var output = phrase.RemoveAccents().ToLower();  
  
    output = Regex.Replace(output, @"\[^A-Za-z0-9\\s-\]", "");  
  
    output = Regex.Replace(output, @"\\s+", " ").Trim();  
  
    output = Regex.Replace(output, @"\\s", "-");  
  
    return output;  
}  
  
public static string RemoveAccents(this string text)  
{  
    if (string.IsNullOrWhiteSpace(text))  
        return text;  
  
    text = text.Normalize(NormalizationForm.FormD);  
    char\[\] chars = text  
        .Where(c => CharUnicodeInfo.GetUnicodeCategory(c)  
        != UnicodeCategory.NonSpacingMark).ToArray();  
  
    return new string(chars).Normalize(NormalizationForm.FormC);  
}

检查电子邮件是否有效

public static bool IsValidEmail(this string email)  
{  
    var isValid = true;  
  
    try  
    {  
        var emailAddress = new MailAddress(email.Trim());  
    }  
    catch  
    {  
        isValid = false;  
    }  
  
    return isValid;  
}
相关留言评论
昵称:
邮箱:
阅读排行