{"id":347,"date":"2009-04-27T19:46:23","date_gmt":"2009-04-27T18:46:23","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=347"},"modified":"2021-03-11T09:44:25","modified_gmt":"2021-03-11T08:44:25","slug":"argument-validation-utility","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2009\/04\/argument-validation-utility\/","title":{"rendered":"Argument Validation Utility"},"content":{"rendered":"<p>A while ago I\u2019ve found a nice way to implement argument validation on the <a href=\"http:\/\/blog.getpaint.net\/2008\/12\/06\/a-fluent-approach-to-c-parameter-validation\/\">Paint.Net-blog<\/a>. Its a fluent-interface like this:<\/p>\n<blockquote>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">void<\/span> CallMe(<span class=\"kwrd\">object<\/span> sender,<span class=\"kwrd\">int<\/span> size, <span class=\"kwrd\">string<\/span> name)\r\n{\r\n    Validate.Begin()\r\n        .IsType&lt;Guid&gt;(sender, <span class=\"str\">\"sender\"<\/span>)\r\n        .BiggerThan(size, 0, <span class=\"str\">\"size\"<\/span>)\r\n        .IsNotEmpty(name, <span class=\"str\">\"name\"<\/span>)\r\n        .Check();\r\n    <span class=\"rem\">\/*IMPL *\/<\/span>\r\n}<\/pre>\n<\/blockquote>\n<p>If only condition fails,<\/p>\n<blockquote><p>CallMe(Guid.NewGuid(), 2, <span class=\"str\">&#8220;&#8221;<\/span>);<\/p><\/blockquote>\n<p>you get a normal exception:<\/p>\n<blockquote><p>System.ArgumentException: The argument &#8216;name&#8217; cannot be empty<\/p><\/blockquote>\n<p>But if more than one condition fails,<\/p>\n<blockquote><p>CallMe(&#8220;I&#8217;m not a guid&#8221;, 0, null);<\/p><\/blockquote>\n<p>you get an exception which reports each violation:<\/p>\n<blockquote><p>Core.IoC.Utils.MultiException: Validation failed with multiple causes:<\/p>\n<p>The parameter &#8216;sender&#8217; is not of type: &#8216;System.Guid&#8217;. Instance: &#8216;I&#8217;m not a guid&#8217; of type: System.String<\/p>\n<p>Expected that the argument &#8216;size&#8217; is bigger than 0 but is is 0<\/p>\n<p>Value cannot be null. Parameter name: name<\/p><\/blockquote>\n<p>Its even possible to iterate over the inner exceptions if necessary:<\/p>\n<blockquote>\n<pre class=\"csharpcode\"><span class=\"kwrd\">try<\/span>{\r\n    CallMe(<span class=\"str\">\"I'm not a guid\"<\/span>, 0, <span class=\"kwrd\">null<\/span>);\r\n} <span class=\"kwrd\">catch<\/span>(MultiException ex)\r\n{\r\n    <span class=\"kwrd\">foreach<\/span> (var singleException <span class=\"kwrd\">in<\/span> ex.InnerExceptions)\r\n    {\r\n        Console.Out.WriteLine(singleException);\r\n    }\r\n}<\/pre>\n<\/blockquote>\n<p>Now to the clever implementation. All the checks are actually extension-methods, which extend the Validation-class. Now, the initial Validate.Begin()-Method return null! Each validation-method first checks its validation. If it fails, it checks if a Validation-class instance is there or not. If so, it adds its exception, if not, it creates the Validation class instance. The final Check-method then tests if there is actually a Validation class instance and throws the exceptions if necessary. With this clever trick, the validation-checks never allocate any object until there is an exception to throw (more detailed on the <a href=\"http:\/\/blog.getpaint.net\/2008\/12\/06\/a-fluent-approach-to-c-parameter-validation\/\">Paint.Net-blog<\/a>)<\/p>\n<blockquote>\n<div style=\"overflow: auto\">\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">class<\/span> Validate\r\n{\r\n\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> Validation Begin()\r\n    {\r\n        <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">null<\/span>;\r\n    }\r\n}\r\n\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">sealed<\/span> <span class=\"kwrd\">class<\/span> Validation\r\n{\r\n    <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">readonly<\/span> List&lt;Exception&gt; exceptions = <span class=\"kwrd\">new<\/span> List&lt;Exception&gt;(1);\r\n\r\n    <span class=\"kwrd\">internal<\/span> Validation()\r\n    {\r\n    }\r\n\r\n    <span class=\"kwrd\">internal<\/span> IEnumerable&lt;Exception&gt; Exceptions\r\n    {\r\n        get { <span class=\"kwrd\">return<\/span> exceptions; }\r\n    }\r\n\r\n    <span class=\"kwrd\">internal<\/span> Validation AddException(Exception ex)\r\n    {\r\n        exceptions.Add(ex);\r\n        <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">this<\/span>;\r\n    }\r\n}\r\n\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">class<\/span> ValidationExtensions\r\n{\r\n    <span class=\"rem\">\/\/\/ *snip* documentation<\/span>\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> Validation IsNotNull&lt;T&gt;(<span class=\"kwrd\">this<\/span> Validation validation, T theObject, <span class=\"kwrd\">string<\/span> argumentName) <span class=\"kwrd\">where<\/span> T : <span class=\"kwrd\">class<\/span>\r\n    {\r\n        <span class=\"kwrd\">if<\/span> (theObject == <span class=\"kwrd\">null<\/span>)\r\n        {\r\n            <span class=\"kwrd\">return<\/span> (validation ?? <span class=\"kwrd\">new<\/span> Validation()).AddException(<span class=\"kwrd\">new<\/span> ArgumentNullException(argumentName));\r\n        }\r\n        <span class=\"kwrd\">return<\/span> validation;\r\n    }\r\n\r\n    <span class=\"rem\">\/* more checks *\/<\/span>\r\n\r\n    <span class=\"rem\">\/\/\/ *snip* documentation<\/span>\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> Validation Check(<span class=\"kwrd\">this<\/span> Validation validation)\r\n    {\r\n        <span class=\"kwrd\">if<\/span> (validation == <span class=\"kwrd\">null<\/span>) <span class=\"kwrd\">return<\/span> validation;\r\n        {\r\n            <span class=\"kwrd\">if<\/span> (validation.Exceptions.Take(2).Count() == 1)\r\n            {\r\n                <span class=\"kwrd\">throw<\/span> validation.Exceptions.First();\r\n            }\r\n            var messages = <span class=\"kwrd\">new<\/span> StringBuilder(<span class=\"str\">\"Validation Failed with multiple causes:\"<\/span>);\r\n            messages.AppendLine();\r\n            <span class=\"kwrd\">foreach<\/span> (var exception <span class=\"kwrd\">in<\/span> validation.Exceptions)\r\n            {\r\n                messages.AppendLine(exception.Message);\r\n            }\r\n            <span class=\"kwrd\">throw<\/span> <span class=\"kwrd\">new<\/span> MultiException(messages.ToString(), validation.Exceptions);\r\n        }\r\n    }\r\n}\r\n\r\n[Serializable]\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> MultiException : ArgumentException\r\n{\r\n\r\n    <span class=\"kwrd\">internal<\/span> MultiException(<span class=\"kwrd\">string<\/span> message, IEnumerable&lt;Exception&gt; exceptions) : <span class=\"kwrd\">base<\/span>(message)\r\n    {\r\n        InnerExceptions = exceptions;\r\n    }\r\n\r\n    <span class=\"rem\">\/* snip some irrelavant stuff *\/<\/span>\r\n\r\n    <span class=\"kwrd\">public<\/span> IEnumerable&lt;Exception&gt; InnerExceptions { get; <span class=\"kwrd\">private<\/span> set; }\r\n\r\n    <span class=\"rem\">\/* snip serialisation-stuff *\/<\/span>\r\n}<\/pre>\n<\/div>\n<\/blockquote>\n<p>As far as I know with .NET 4.0 some <a href=\"http:\/\/research.microsoft.com\/en-us\/projects\/contracts\/\">kind of contracts<\/a> will be introduced to the core framework. Then I will start to use those, to benefit from the better tool support.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A while ago I\u2019ve found a nice way to implement argument validation on the Paint.Net-blog. Its a fluent-interface like this: public void CallMe(object sender,int size, string name) { Validate.Begin() .IsType&lt;Guid&gt;(sender,&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[126,17],"tags":[21,24],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/347"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=347"}],"version-history":[{"count":8,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/347\/revisions"}],"predecessor-version":[{"id":3754,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/347\/revisions\/3754"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}