Business Object Validation Using Attributes in C#

本文介绍了一种使用C#属性进行业务对象验证的方法。通过自定义属性实现数据验证逻辑,简化了验证过程并提高了代码可读性和可维护性。

Business Object Validation Using Attributes in C#

7/14/2009

Ok, so there are about 9,000,000 different implementations out there when it comes to validating business objects. Although most of the ones that I see out there are simply tweaked versions ofCSLA.Net. Personally I'm not a big fan of that approach. It works quite well but I just wanted to try something else, so instead I tried out the second most popular approach... Attributes. I know that usually I groan whenever I think about attributes but it actually works pretty well in this instance.

   1: public class Test
   2: {
   3:     [Between(1,4,"This item needs to be between 1 and 4")]
   4:     public int Value{get;set;}
   5: }

That's not that bad. Even if I have ten properties, that isn't that bad. And implementing the attributes themselves is simple as well:

   1: [AttributeUsage(AttributeTargets.Property,AllowMultiple=false)]
   2: public class BaseAttribute:Attribute
   3: {
   4:     public BaseAttribute(string ErrorMessage)
   5:     {
   6:         this.ErrorMessage = ErrorMessage;
   7:     }
   8:  
   9:     public string ErrorMessage { get; set; }
  10:  
  11:     internal virtual string IsValid(PropertyInfo Property,object Object)
  12:     {
  13:         return ErrorMessage;
  14:     }
  15: } 
  16:  
  17: public class Between : BaseAttribute
  18: {
  19:     public Between(object MinValue,object MaxValue, string ErrorMessage)
  20:         : base(ErrorMessage)
  21:     {
  22:         this.MinValue = MinValue;
  23:         this.MaxValue = MaxValue;
  24:     }
  25:  
  26:     public object MinValue { get; set; }
  27:     public object MaxValue { get; set; }
  28:  
  29:     internal override string IsValid(PropertyInfo Property, object Object)
  30:     {
  31:         object Value = Property.GetValue(Object, null);
  32:         if (Value is DateTime && (DateTime)Value <= DateTime.Parse(this.MaxValue.ToString()) && (DateTime)Value >= DateTime.Parse(this.MinValue.ToString()))
  33:             return "";
  34:         else if (Value is DateTime)
  35:             return ErrorMessage;
  36:         else if (double.Parse(Value.ToString()) <= double.Parse(this.MaxValue.ToString()) && double.Parse(Value.ToString()) >= double.Parse(this.MinValue.ToString()))
  37:             return "";
  38:         return ErrorMessage;
  39:     }
  40: }

That's it, a constructor, some fields to hold our information, and one function. We do however have to find the attributes and call the function to even check the property, but with a bit of reflection that's pretty simple:

   1: public static class ValidationManager
   2: {
   3:     public static bool Validate(object Object)
   4:     {
   5:         StringBuilder Builder = new StringBuilder();
   6:         if (Object != null)
   7:         {
   8:             Type ObjectType = Object.GetType();
   9:             PropertyInfo[] Properties = ObjectType.GetProperties();
  10:             foreach (PropertyInfo Property in Properties)
  11:             {
  12:                 object[] Attributes = Property.GetCustomAttributes(typeof(BaseAttribute), true);
  13:                 foreach (object Attribute in Attributes)
  14:                 {
  15:                     Builder.Append(((BaseAttribute)Attribute).IsValid(Property, Object));
  16:                 }
  17:             }
  18:         }
  19:         if(string.IsNullOrEmpty(Builder.ToString()))
  20:             return true;
  21:         throw new NotValid(Builder.ToString());
  22:     }
  23: }

That's it really. We just call the Validate function, passing in our object, and in turn  the function gets all of the properties, finds the attributes, and calls the IsValid function appropriately. And because all of our attributes inherit from BaseAttribute, all we need to do is create a new one and the function will automatically pick it up. So if we want one based off of Regex for strings, not a problem:

   1: public class Regex:BaseAttribute
   2: {
   3:     public Regex(string RegexString, string ErrorMessage)
   4:         :base(ErrorMessage)
   5:     {
   6:         this.RegexString = RegexString;
   7:     }
   8:  
   9:     public string RegexString { get; set; }
  10:  
  11:     internal override string IsValid(PropertyInfo Property, object Object)
  12:     {
  13:         object Value = Property.GetValue(Object, null);
  14:         if (Value is String)
  15:         {
  16:             System.Text.RegularExpressions.Regex TempRegex = new System.Text.RegularExpressions.Regex(RegexString);
  17:             if (TempRegex.IsMatch((string)Value))
  18:                 return "";
  19:         }
  20:         return ErrorMessage;
  21:     }
  22: }

Hell if we want to have the ability to cascade and check classes, we can:

   1: public class Cascade:BaseAttribute
   2: {
   3:     public Cascade()
   4:         : base("")
   5:     {
   6:     }
   7:  
   8:     internal override string IsValid(PropertyInfo Property, object Object)
   9:     {
  10:         object Value = Property.GetValue(Object, null);
  11:         if (Property.PropertyType.FullName.StartsWith("System.Collections.Generic.List", StringComparison.CurrentCultureIgnoreCase))
  12:         {
  13:             Type ListType = Value.GetType();
  14:             PropertyInfo IndexProperty = ListType.GetProperty("Item");
  15:             PropertyInfo CountProperty = ListType.GetProperty("Count");
  16:             int Count = (int)CountProperty.GetValue(Value, null);
  17:             for (int x = 0; x < Count; ++x)
  18:             {
  19:                 object IndexedObject = IndexProperty.GetValue(Value, new object[] { x });
  20:                 if (IndexedObject != null)
  21:                 {
  22:                     try
  23:                     {
  24:                         ValidationManager.Validate(IndexedObject);
  25:                     }
  26:                     catch (NotValid e) { return Property.Name + "(" + x + ") : " + e.Message; }
  27:                 }
  28:             }
  29:         }
  30:         else
  31:         {
  32:             if (Value != null)
  33:             {
  34:                 try
  35:                 {
  36:                     ValidationManager.Validate(Value);
  37:                 }
  38:                 catch (NotValid e) { return Property.Name + " : " + e.Message; }
  39:             }
  40:         }
  41:         return "";
  42:     }
  43: }

Heck in the one above, we can even check if this is a list and go through each item in the list... And when we're done creating the attribute, we just tack it on our properties and we're done. So try it out, leave feedback, and happy coding.

内容概要:本文是一篇关于使用RandLANet模型对SensatUrban数据集进行点云语义分割的实战教程,系统介绍了从环境搭建、数据准备、模型训练与测试到精度评估的完整流程。文章详细说明了在Ubuntu系统下配置TensorFlow 2.2、CUDA及cuDNN等深度学习环境的方法,并指导用户下载和预处理SensatUrban数据集。随后,逐步讲解RandLANet代码的获取与运行方式,包括训练、测试命令的执行与参数含义,以及如何监控训练过程中的关键指标。最后,教程涵盖测试结果分析、向官方平台提交结果、解读评估报告及可视化效果等内容,并针对常见问题提供解决方案。; 适合人群:具备一定深度学习基础,熟悉Python编程和深度学习框架,从事计算机视觉或三维点云相关研究的学生、研究人员及工程师;适合希望动手实践点云语义分割项目的初学者与进阶者。; 使用场景及目标:①掌握RandLANet网络结构及其在点云语义分割任务中的应用;②学会完整部署一个点云分割项目,包括数据处理、模型训练、测试与性能评估;③为参与相关竞赛或科研项目提供技术支撑。; 阅读建议:建议读者结合提供的代码链接和密码访问完整资料,在本地或云端环境中边操作边学习,重点关注数据格式要求与训练参数设置,遇到问题时参考“常见问题与解决技巧”部分及时排查。
内容概要:本文详细介绍了三相异步电机SVPWM-DTC(空间矢量脉宽调制-直接转矩控制)的Simulink仿真实现方法,结合DTC响应快与SVPWM谐波小的优点,构建高性能电机控制系统。文章系统阐述了控制原理,包括定子磁链观测、转矩与磁链误差滞环比较、扇区判断及电压矢量选择,并通过SVPWM技术生成固定频率PWM信号,提升系统稳态性能。同时提供了完整的Simulink建模流程,涵盖电机本体、磁链观测器、误差比较、矢量选择、SVPWM调制、逆变器驱动等模块的搭建与参数设置,给出了仿真调试要点与预期结果,如电流正弦性、转矩响应快、磁链轨迹趋圆等,并提出了模型优化与扩展方向,如改进观测器、自适应滞环、弱磁控制和转速闭环等。; 适合人群:电气工程、自动化及相关专业本科生、研究生,从事电机控制算法开发的工程师,具备一定MATLAB/Simulink和电机控制理论基础的技术人员。; 使用场景及目标:①掌握SVPWM-DTC控制策略的核心原理与实现方式;②在Simulink中独立完成三相异步电机高性能控制系统的建模与仿真;③通过仿真验证控制算法有效性,为实际工程应用提供设计依据。; 阅读建议:学习过程中应结合文中提供的电机参数和模块配置逐步搭建模型,重点关注磁链观测、矢量选择表和SVPWM调制的实现细节,仿真时注意滞环宽度与开关频率的调试,建议配合MATLAB官方工具箱文档进行参数校准与结果分析。
已经博主授权,源码转载自 https://pan.quark.cn/s/bf1e0d5b9490 本文重点阐述了Vue2.0多Tab切换组件的封装实践,详细说明了通过封装Tab切换组件达成多Tab切换功能,从而满足日常应用需求。 知识点1:Vue2.0多Tab切换组件的封装* 借助封装Tab切换组件,达成多Tab切换功能* 支持tab切换、tab定位、tab自动化仿React多Tab实现知识点2:TabItems组件的应用* 在index.vue文件中应用TabItems组件,借助name属性设定tab的标题* 通过:isContTab属性来设定tab的内容* 能够采用子组件作为tab的内容知识点3:TabItems组件的样式* 借助index.less文件来设定TabItems组件的样式* 设定tab的标题样式、背景色彩、边框样式等* 使用animation达成tab的切换动画知识点4:Vue2.0多Tab切换组件的构建* 借助运用Vue2.0框架,达成多Tab切换组件的封装* 使用Vue2.0的组件化理念,达成TabItems组件的封装* 通过运用Vue2.0的指令和绑定机制,达成tab的切换功能知识点5:Vue2.0多Tab切换组件的优势* 达成多Tab切换功能,满足日常应用需求* 支持tab切换、tab定位、tab自动化仿React多Tab实现* 能够满足多样的业务需求,具备良好的扩展性知识点6:Vue2.0多Tab切换组件的应用场景* 能够应用于多样的业务场景,例如:管理系统、电商平台、社交媒体等* 能够满足不同的业务需求,例如:多Tab切换、数据展示、交互式操作等* 能够与其它Vue2.0组件结合运用,达成复杂的业务逻辑Vue2.0多Tab切换组件的封装实例提供了...
代码下载地址: https://pan.quark.cn/s/41cd695ddf65 `htmldiff` 是一个以 Ruby 语言为基础构建的库,其主要功能是在 HTML 文档中展示文本之间的差异。 该库的一个显著特点在于它不仅能够识别出不同之处,还会借助 HTML 标签来呈现这些差异,从而让用户能够直观地观察到文本的变化情况。 这种特性使得 `htmldiff` 在版本控制、文档对比或任何需要展示文本变动场景的应用中显得尤为有用。 `htmldiff` 的核心作用是对比两个字符串,并生成一个 HTML 输出结果,这个结果会明确地指出哪些部分被添加、哪些部分被删除以及哪些部分被修改。 此外,通过运用 CSS,用户可以进一步调整差异展示的样式,使其与项目或网站的现有设计风格相协调。 在使用 `htmldiff` 之前,需要先完成该库的安装。 如果项目已经配置了 Ruby 环境和 Gemfile,可以在 Gemfile 文件中添加 `gem htmldiff` 语句,随后执行 `bundle install` 命令进行安装。 如果没有 Gemfile 文件,也可以直接采用 `gem install htmldiff` 命令来进行全局安装。 在编程实现时,可以通过调用 `Htmldiff.diff` 方法来对比两个字符串,并获取相应的 HTML 输出。 例如:```rubyrequire htmldiffstr1 = "这是一个示例文本。 "str2 = "这是一个示例文本,现在有更多内容。 "diff_html = Htmldiff.diff(str1, str2)puts diff_html```上述代码将会输出两个字符串之间的差异,其中新增的内容会被 `<ins>` 标签所包围,而...
源码地址: https://pan.quark.cn/s/4b03c5611266 依据所提供的资料,可以判定这份资料是关于《电子技术基础模拟部分》第五版教科书第七章节的习题解析,由湖南人文科技学院通信与控制工程系的田汉平教师提供。 尽管具体内容未予展示,但能够围绕模拟电子技术的基础理论、第七章节所涉及的核心概念以及潜在的习题种类等方面来展开相关知识点的阐述。 ### 模拟电子技术概述模拟电子技术是电子工程学科中的一个关键领域,主要探讨模拟信号的产生、转换、传输和处理等议题。 模拟信号是指时间与幅度上均呈现连续变化的电信号。 模拟电路的设计与剖析是模拟电子技术的核心,它涵盖了放大器、振荡器、滤波器等电路的设计原理及其应用。 ### 第七章核心知识点猜测#### 1. 放大电路分析与设计- **基本放大电路**:共射极、共基极和共集电极放大电路的特性及其应用场景。 - **多级放大电路**:掌握如何将多个放大电路串联,以提升增益或优化频率响应。 - **差分放大电路**:用于抑制共模信号,放大差模信号,是精密仪器和测量设备中的关键构成部分。 #### 2. 反馈电路与稳定性- **反馈的基本概念**:正反馈与负反馈的区分,以及它们在电路中的应用场景。 - **深度负反馈**:解析深度负反馈状态下的放大器性能改进,包括增益稳定性和带宽的拓宽。 - **振荡电路**:理解LC振荡器、RC振荡器的工作机制及应用领域。 #### 3. 功率放大器- **A类、B类、AB类功率放大器**:熟练掌握不同类型功率放大器的特性、效率及其适用环境。 - **热效应与保护措施**:讨论在功率放大器设计过程中需要关注的散热问题及相应的防护措施。 #### 4. 集成运算放大器的应用- **理想运放模型**:熟...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值