用C#写一个灵活的要素Feature属性Properties质检WebAPI接口(三)

本文介绍一下功能实现,并给出核心部分代码。

首先要定义各种结构,包括传入参数、传出结果、规则集合等,如下:

using GeoJSON.Net.Feature;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;

namespace GISWebService.HttpRequestContent
{
    /// <summary>
    /// 属性质检的传入参数
    /// </summary>
    public class CheckFields
    {
        /// <summary>
        /// 图层
        /// </summary>
        [JsonProperty("layer")]
        public string Layer { get; set; }
        /// <summary>
        /// 要素集合
        /// </summary>
        [JsonProperty("feature")]
        public List<Feature> Feature { get; set; }
    }


    /// <summary>
    /// 要素属性质检结果
    /// </summary>
    public class CheckFieldsResult
    {
        /// <summary>
        /// OBJECTID
        /// </summary>
        [JsonProperty("objectid")]
        public int ObjectID { get; set; }
        /// <summary>
        /// 字段检查结果
        /// </summary>
        [JsonProperty("fields")]
        public List<string> FieldInfo { get; set; }
    }

    /// <summary>
    /// 属性质检结果
    /// </summary>
    public class CheckFieldsResponseBody
    {
        /// <summary>
        /// 图层
        /// </summary>
        [JsonProperty("layer")]
        public string Layer { get; set; }
        /// <summary>
        /// 质检结果
        /// </summary>
        [JsonProperty("info")]
        public List<CheckFieldsResult> Information { get; set; }
    }

    /// <summary>
    /// 规则:来自集合
    /// </summary>
    public class RuleCollection
    {
        /// <summary>
        /// 分隔符
        /// </summary>
        [JsonProperty("seperator")]
        [DefaultValue(",")]
        public string Seperator { get; set; }
        /// <summary>
        /// 集合
        /// </summary>
        [JsonProperty("list")]
        [JsonConverter(typeof(ValueToList))]
        public List<string> Items { get; set; }
    }

    /// <summary>
    /// 属性值质检规则
    /// </summary>
    public class RuleValueItem
    {
        /// <summary>
        /// 字段名
        /// </summary>
        [JsonProperty("name")]
        public string FieldName { get; set; }
        /// <summary>
        /// 允许空值(默认为true)
        /// </summary>
        [JsonProperty("nullable")]
        [DefaultValue(true)]
        public bool Nullable { get; set; }
        /// <summary>
        /// 来自集合
        /// </summary>
        [JsonProperty("collection", NullValueHandling = NullValueHandling.Ignore)]
        public RuleCollection RuleOfCollection { get; set; }
        /// <summary>
        /// 正则表达式
        /// </summary>
        [JsonProperty("expression", NullValueHandling = NullValueHandling.Ignore)]
        public string RegExp { get; set; }
    }

    /// <summary>
    /// 要素类属性值质检规则
    /// </summary>
    public class RuleValue
    {
        /// <summary>
        /// 要素类集合
        /// </summary>
        [JsonProperty("featureclass")]
        public List<string> FeatureClassNames { get; set; }
        /// <summary>
        /// 各字段规则
        /// </summary>
        [JsonProperty("rule")]
        public List<RuleValueItem> RuleItems { get; set; }
    }

    /// <summary>
    /// 属性空值限制质检规则
    /// </summary>
    public class RuleRestrictionItem
    {
        /// <summary>
        /// 主干(非空时要求分支不为空)
        /// </summary>
        [JsonProperty("trunk")]
        public string Trunk { get; set; }
        /// <summary>
        /// 分支
        /// </summary>
        [JsonProperty("branch")]
        [DefaultValue(true)]
        public List<string> Branches { get; set; }
    }

    /// <summary>
    /// 要素类属性值质检规则
    /// </summary>
    public class RuleRestriction
    {
        /// <summary>
        /// 要素类集合
        /// </summary>
        [JsonProperty("featureclass")]
        public List<string> FeatureClassNames { get; set; }
        /// <summary>
        /// 属性空值限制质检规则
        /// </summary>
        [JsonProperty("rule")]
        public List<RuleRestrictionItem> RuleItems { get; set; }
    }


    /// <summary>
    /// 属性空值限制质检规则
    /// </summary>
    public class RuleRelationItem
    {
        /// <summary>
        /// 较短的字段
        /// </summary>
        [JsonProperty("short")]
        public string ShortField { get; set; }
        /// <summary>
        /// 较长的字段(非空时,较短字段为其取值的一部分)
        /// </summary>
        [JsonProperty("long")]
        public string LongField { get; set; }

        /// <summary>
        /// 起始索引(从1起算,取值包含该索引)
        /// </summary>
        [JsonProperty("from")]
        public int FromIndex { get; set; }
        /// <summary>
        /// 终止索引(从1起算,大于起始索引,但小于总长度,取值包含该索引)
        /// </summary>
        [JsonProperty("to")]
        public int ToIndex { get; set; }
    }

    /// <summary>
    /// 要素类属性关系质检规则
    /// </summary>
    public class RuleRelation
    {
        /// <summary>
        /// 要素类集合
        /// </summary>
        [JsonProperty("featureclass")]
        public List<string> FeatureClassNames { get; set; }
        /// <summary>
        /// 属性关系质检规则
        /// </summary>
        [JsonProperty("rule")]
        public List<RuleRelationItem> RuleItems { get; set; }
    }

    public class ValueToList : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            bool isTypeNullable = IsNullableType(objectType);
            Type t = isTypeNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
            if (reader.TokenType == JsonToken.Null)
            {
                if (!IsNullableType(objectType))
                    throw new Exception(string.Format("不能转换null value to {0}.", objectType));
                return null;
            }
            try
            {
                List<string> ls = new List<string>();
                if (reader.TokenType == JsonToken.String)
                {
                    string sValue = reader.Value.ToString();
                    string[] arrayValue = sValue.Split(',');
                    foreach (string s in arrayValue)
                    {
                        if (string.IsNullOrWhiteSpace(s))
                            continue;
                        ls.Add(s);
                    }
                }
                return ls;
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error converting value {0} to type '{1}'", reader.Value, objectType));
            }
            throw new Exception(string.Format("Unexpected token {0} when parsing enum", reader.TokenType));
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (null == value)
            {
                writer.WriteNull();
                return;
            }
            List<string> ls = value as List<string>;
            if (null == ls || 0 == ls.Count)
            {
                writer.WriteNull();
                return;
            }
            string result = "";
            foreach (string s in ls)
            {
                if (string.IsNullOrEmpty(s) || string.IsNullOrWhiteSpace(s))
                    continue;
                if (string.IsNullOrEmpty(result))
                {
                    result = s;
                }
                else
                {
                    result += "," + s;
                }
            }
            writer.WriteValue(result);
        }

        public bool IsNullableType(Type t)
        {
            if (t == null)
            {
                throw new ArgumentNullException("t");
            }
            return (t.BaseType.FullName == "System.ValueType" && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }
    }
}

先定义一个CheckValue类,来实现属性质检规则的加载:

using GeoJSON.Net.Feature;
using GISWebService.HttpRequestContent;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace GISWebService.Common
{
    public class CheckValue
    {
        private static string _CheckRelationConfig = "CheckRelation.json";
        private static string _CheckRestrictionConfig = "CheckRestriction.json";
        private static string _CheckValueConfig = "CheckValue.json";

        private static List<RuleRelation> _RuleRelations = null;
        private static List<RuleRestriction> _RuleRestrictions = null;
        private static List<RuleValue> _RuleValues = null;
        /// <summary>
        /// 属性关系检查规则
        /// </summary>
        public static List<RuleRelation> RuleRelations { get { return GetRules<RuleRelation>(_CheckRelationConfig, _RuleRelations as System.Collections.IList) as List<RuleRelation>; } }
        /// <summary>
        /// 属性空值约束检查规则
        /// </summary>
        public static List<RuleRestriction> RuleRestrictions { get { return GetRules<RuleRestriction>(_CheckRestrictionConfig, _RuleRestrictions as System.Collections.IList) as List<RuleRestriction>; } }
        /// <summary>
        /// 属性值检查规则
        /// </summary>
        public static List<RuleValue> RuleValues { get { return GetRules<RuleValue>(_CheckValueConfig, _RuleValues as System.Collections.IList) as List<RuleValue>; } }

        private static System.Collections.IList GetRules<T>(string name, System.Collections.IList rules)
        {
            if (null == rules)
            {
                Type aType = typeof(List<>).MakeGenericType(typeof(T));
                rules = Activator.CreateInstance(aType) as System.Collections.IList;
            }
            if (0 == rules.Count)
                rules = LoadRules<T>(name);
            return rules;
        }

        private static string GetConfigFile(string name)
        {
            string path = "";
            try
            {
                string s = System.IO.Path.Combine(AppSettings.PathByKey("tempdir"), name);
                path = System.IO.File.Exists(s) ? s : "";
            }
            catch (Exception e)
            {
                ExceptionHelper.LogActionException(e);
            }
            return path;
        }

        private static System.Collections.IList LoadRules<T>(string name)
        {
            string sPath = GetConfigFile(name);
            Type aType = typeof(List<>).MakeGenericType(typeof(T));
            System.Collections.IList ls = Activator.CreateInstance(aType) as System.Collections.IList;
            if (!string.IsNullOrEmpty(sPath))
            {
                string sContent = System.IO.File.ReadAllText(sPath, System.Text.Encoding.Default);
                ls = Newtonsoft.Json.JsonConvert.DeserializeObject(sContent, aType) as System.Collections.IList;
            }
            return ls;
        }

    }
}

在核心的质检类CheckValueHelper类中定义质检的方法,并让它继承自CheckValue类:

using GeoJSON.Net.Feature;
using GISWebService.HttpRequestContent;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;

namespace GISWebService.Common
{
    public class CheckValueHelper : CheckValue
    {
        public static CheckFieldsResult Check(string featureclass, Feature feature)
        {
            CheckFieldsResult result = new CheckFieldsResult() { ObjectID = -1, FieldInfo = new List<string>() };
            int oid = GetObjectID(feature);
            if (0 <= oid)
            {
                result.ObjectID = oid;
                result.FieldInfo.AddRange(CheckRelation(featureclass, feature.Properties, RuleRelations));
                result.FieldInfo.AddRange(CheckRestriction(featureclass, feature.Properties, RuleRestrictions));
                result.FieldInfo.AddRange(CheckValue(featureclass, feature.Properties, RuleValues));
            }
            return result;
        }

        private static int GetObjectID(Feature feature)
        {
            int n = -1;
            if (null == feature || null == feature.Properties || 0 == feature.Properties.Count)
                return n;
            foreach (var item in feature.Properties)
            {
                if (0 == string.Compare(item.Key, "objectid", true))
                {
                    if (null == item.Value)
                        continue;
                    int oid = -1;
                    if (int.TryParse(item.Value.ToString(), out oid) && 0 < oid)
                    {
                        n = Convert.ToInt32(item.Value.ToString());
                        break;
                    }
                }
            }
            return n;
        }

        private static string GetValueToString(Dictionary<string, object> dict, string key, bool ignoreCase = true, bool removeWhitespace = true)
        {
            string s = "";
            if (null == dict || 0 == dict.Count || string.IsNullOrEmpty(key))
                return s;
            foreach (var item in dict)
            {
                if (0 == string.Compare(item.Key, key, ignoreCase) && item.Value != null)
                {
                    s = removeWhitespace ? item.Value.ToString().Replace(" ", "") : item.Value.ToString();
                    break;
                }
            }
            return s;
        }

        private static List<string> CheckRelation(string featureclass, Dictionary<string, object> dict, List<RuleRelation> lsRule)
        {
            int nA = -1;
            for (int n = 0; n < lsRule.Count; n++)
            {
                int m = lsRule[n].FeatureClassNames.FindIndex((e) => { return 0 == string.Compare(e, featureclass, true); });
                if (m >= 0)
                {
                    nA = n;
                    break;
                }
            }
            if (nA < 0)
                return null;

            List<string> ls = new List<string>();
            List<RuleRelationItem> lsRuleItem = lsRule[nA].RuleItems;
            foreach (var item in lsRuleItem)
            {
                if (string.IsNullOrEmpty(item.ShortField) || string.IsNullOrEmpty(item.LongField) || item.FromIndex <= 0 || item.ToIndex <= 0 || item.FromIndex > item.ToIndex)
                {
                    Log.Loging.Info(string.Format("关联检查配置文件有误。Long = {0}, Short = {1}, From = {2} ,To = {3}", item.LongField, item.ShortField, item.FromIndex, item.ToIndex));
                    continue;
                }
                string sShortLengthValue = GetValueToString(dict, item.ShortField);
                string sLongLengthValue = GetValueToString(dict, item.LongField);
                if (string.IsNullOrEmpty(sShortLengthValue) || string.IsNullOrEmpty(sLongLengthValue))
                {
                    Log.Loging.Info(string.Format("有数据为空。{0} = {1}, {2} = {3}", item.ShortField, sShortLengthValue, item.LongField, sLongLengthValue));
                    continue;
                }
                if (sLongLengthValue.Length < item.ToIndex)
                {
                    Log.Loging.Info(string.Format("数据有误,{0} 字段取值 {1} 未能超过索引长度 {2}", item.LongField, sLongLengthValue, item.ToIndex));
                    continue;
                }
                string sSubString = sLongLengthValue.Substring(item.FromIndex - 1, item.ToIndex - item.FromIndex + 1);
                if (0 != string.Compare(sShortLengthValue, sSubString, true))
                {
                    if (item.FromIndex == item.ToIndex)
                        ls.Add(string.Format("字段 {0} 取值不为字段 {1} 取值的第 {2} 位", item.ShortField, item.LongField, item.FromIndex));
                    else
                        ls.Add(string.Format("字段 {0} 取值不为字段 {1} 取值的第 {2} 位至第 {3} 位", item.ShortField, item.LongField, item.FromIndex, item.ToIndex));
                }
            }
            return ls;
        }

        private static List<string> CheckRestriction(string featureclass, Dictionary<string, object> dict, List<RuleRestriction> lsRule)
        {
            int nA = -1;
            for (int n = 0; n < lsRule.Count; n++)
            {
                int m = lsRule[n].FeatureClassNames.FindIndex((e) => { return 0 == string.Compare(e, featureclass, true); });
                if (m >= 0)
                {
                    nA = n;
                    break;
                }
            }
            if (nA < 0)
                return null;
            List<string> ls = new List<string>();
            List<RuleRestrictionItem> lsRuleItem = lsRule[nA].RuleItems;
            foreach (var item in lsRuleItem)
            {
                if (string.IsNullOrEmpty(item.Trunk) || null == item.Branches || 0 == item.Branches.Count)
                {
                    Log.Loging.Info("主干字段配置有误");
                    continue;
                }
                string sTrunkFieldValue = GetValueToString(dict, item.Trunk);
                if (string.IsNullOrEmpty(sTrunkFieldValue))
                {
                    Log.Loging.Info(string.Format("不包含字段 {0} 或取值为空", item.Trunk));
                    continue;
                }
                foreach (var branch in item.Branches)
                {
                    if (string.IsNullOrEmpty(branch))
                    {
                        Log.Loging.Info("分支字段配置有误");
                        continue;
                    }
                    string sBrunchFieldValue = GetValueToString(dict, branch);
                    if (string.IsNullOrEmpty(sBrunchFieldValue))
                        ls.Add(string.Format("字段 {0} 不为空时要求字段 {1} 也不能为空", item.Trunk, branch));
                }
            }
            return ls;
        }

        private static List<string> CheckValue(string featureclass, Dictionary<string, object> dict, List<RuleValue> lsRule)
        {
            int nA = -1;
            for (int n = 0; n < lsRule.Count; n++)
            {
                int m = lsRule[n].FeatureClassNames.FindIndex((e) => { return 0 == string.Compare(e, featureclass, true); });
                if (m >= 0)
                {
                    nA = n;
                    break;
                }
            }
            if (nA < 0)
                return null;
            List<string> ls = new List<string>();
            List<RuleValueItem> lsRuleItem = lsRule[nA].RuleItems;
            foreach (var aPair in dict)
            {
                RuleValueItem fieldRule = null;
                for (int k = 0; k < lsRuleItem.Count; k++)
                {
                    if (0 == string.Compare(lsRuleItem[k].FieldName, aPair.Key, true))
                    {
                        fieldRule = lsRuleItem[k];
                        break;
                    }
                }
                if (null == fieldRule)
                    continue;

                string sValue = "";
                if (null != aPair.Value)
                    sValue = aPair.Value.ToString().Replace(" ", "");

                if (!fieldRule.Nullable)
                {
                    if (string.IsNullOrEmpty(sValue))
                    {
                        ls.Add(string.Format("字段 {0} 取值不允许非空", aPair.Key));
                        continue;
                    }
                }

                if (!string.IsNullOrEmpty(sValue) && null != fieldRule.RuleOfCollection)
                {
                    if (null != fieldRule.RuleOfCollection.Items && 0 < fieldRule.RuleOfCollection.Items.Count && !string.IsNullOrEmpty(fieldRule.RuleOfCollection.Seperator))
                    {
                        char[] cSeperator = fieldRule.RuleOfCollection.Seperator.ToCharArray();
                        string[] arrayValue = sValue.Split(cSeperator, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var item in arrayValue)
                        {
                            if (0 > fieldRule.RuleOfCollection.Items.FindIndex(e => { return 0 == string.Compare(item, e, true); }))
                            {
                                ls.Add(string.Format("字段 {0} 取值不在指定的集合范围内", aPair.Key));
                                break;
                            }
                        }
                    }
                }
                if (!string.IsNullOrEmpty(sValue) && !string.IsNullOrEmpty(fieldRule.RegExp))
                {
                    if (!(new Regex(fieldRule.RegExp).IsMatch(sValue)))
                        ls.Add(string.Format("字段 {0} 取值不符合规范", aPair.Key));
                }
            }
            return ls;
        }

    }
}

调用的地方,即接口处实现如下:

        /// <summary>
        /// 属性质检(可配置式)
        /// </summary>
        /// <returns>质检结果</returns>
        /// <status>可用</status>
        [HttpPost]
        [ResponseType(typeof(List<CheckFieldsResponseBody>))]
        public IHttpActionResult CheckFields2([FromBody]List<CheckFields> param)
        {
            try
            {
                List<CheckFieldsResponseBody> lsResult = new List<CheckFieldsResponseBody>() { };
                foreach (var item in param)
                {
                    CheckFieldsResponseBody aResponse = new CheckFieldsResponseBody() { Layer = item.Layer, Information = new List<CheckFieldsResult>() };
                    foreach (var feature in item.Feature)
                        aResponse.Information.Add(CheckValueHelper.Check(aResponse.Layer, feature));
                    lsResult.Add(aResponse);
                }
                return Json(new JObject(new JProperty("status", 0), new JProperty("result", JToken.FromObject(lsResult))));
            }
            catch (Exception e)
            {
                ExceptionHelper.LogActionException(e);
                return Json(new ResponseInfo() { StatusCode = 1, Message = e.Message });
            }
        }


猜你喜欢

转载自blog.csdn.net/a_dev/article/details/80678158