<#@ template debug="false" hostspecific="true" language="C#" #> <#@ output extension=".designer.cs" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.IO" #> <# //========================================== // StringWrapper template v1.0.0 // //------------------------------------------ // Purpose: //------------------------------------------ // // To automatically generate nullable struct around a string. // //------------------------------------------ // Usage: //------------------------------------------ // 1) filename is the name of the new struct. // 2) Set default transform for validation. // var options = new { DefaultTransform = one of "None" | "Trim" | "TrimToUpper" | Path.To.Validation.Function }; // 3) Include this file "FoldStates.ttinclude" // See example below. // //------------------------------------------ // Example for representing board game states // // assume file is called "ProductCode.tt", the file content is: //------------------------------------------ // \<# // var options = new { DefaultTransform = "NotEmptyUppercase" }; // \#> // \<#@ include file="..\StringWrapper.ttinclude" \#> // //========================================== var namespaceHint = System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint"); var structName = Path.GetFileNameWithoutExtension(Host.TemplateFile); string defaultTransform = "null;"; switch (options.DefaultTransform) { case "None": defaultTransform = "null"; break; case "Trim": defaultTransform = "s => { var trimmed = (s ?? \"\").Trim(); return trimmed.Length == 0 ? null : trimmed; }"; break; case "TrimToUpper": defaultTransform = "s => { var trimmed = (s ?? \"\").Trim(); return trimmed.Length == 0 ? null : trimmed.ToUpper(); }"; break; default: defaultTransform = string.Format("s => {0}(s)",options.DefaultTransform); break; } #> // ============================================================================ // Auto-generated. Do not edit! // // To add functionality, create and edit the partial class in a separate file. // ============================================================================ using System; namespace <#= namespaceHint #> { /// /// Struct to wrap strings for DDD, to avoid mixing up string types, and to avoid null strings. /// /// /// structs cannot inherit, so the code is duplicated for each. /// [Serializable] [System.Diagnostics.DebuggerDisplay(@"<#= structName #>\{{Value}\}")] [System.CodeDom.Compiler.GeneratedCodeAttribute("T4Template:StringWrapper.ttinclude","1.0.0")] public partial struct <#= structName #> : IEquatable<<#= structName #>>, IComparable<<#= structName #>> { public string Value { get; private set; } /// /// Create a new struct wrapping a string. /// /// The string to wrap. It must not be null. /// A function to transform and/or validate the string. /// The unwrapped string is passed into the transform function, /// and the transform should return null if the string is not valid, // otherwise the transform should convert the string as needed (eg remove spaces, convert to uppercase, etc). /// A null transform is ignored. /// /// Thrown if the str is null. static public <#= structName #> New(string str, Func transform) { if (transform != null) { str = transform(str); } if (str == null) { throw new ArgumentException("Input to <#= structName #> is not valid","str"); } return new <#= structName #> { Value = str }; } /// /// Create a new struct wrapping a string. /// /// The string to wrap. It must not be null. /// Thrown if the str is null. static public <#= structName #> New(string str) { Func defaultTransform = <#= defaultTransform #>; return New(str, defaultTransform); } /// /// Create a new nullable struct wrapping a string, or null if the string is null or invalid. /// /// The string to wrap. If is is null or invalid, null is returned. /// A function to transform and/or validate the string. /// The unwrapped string is passed into the transform function, /// and the transform should return null if the string is not valid, // otherwise the transform should convert the string as needed (eg remove spaces, convert to uppercase, etc). /// A null transform is ignored. /// static public <#= structName #>? NewOption(string str, Func transform) { if (transform != null) { str = transform(str); } if (str == null) { return null; } return new <#= structName #> { Value = str }; } /// /// Create a new nullable struct wrapping a string, or null if the string is null. /// /// The string to wrap. If is is null, null is returned. static public <#= structName #>? NewOption(string str) { Func defaultTransform = <#= defaultTransform #>; return NewOption(str, defaultTransform); } public override string ToString() { return Value; } public override bool Equals(object other) { return other is <#= structName #> && Equals((<#= structName #>)other); } public bool Equals(<#= structName #> other) { return Value.Equals(other.Value, StringComparison.InvariantCulture); } public override int GetHashCode() { return Value.GetHashCode(); } public static bool operator ==(<#= structName #> lhs, <#= structName #> rhs) { return lhs.Equals(rhs); } public static bool operator !=(<#= structName #> lhs, <#= structName #> rhs) { return !lhs.Equals(rhs); } public int CompareTo(<#= structName #> other) { return String.CompareOrdinal(Value, other.Value); } } /// /// Extensions to convert strings into <#= structName #>s. /// public static class <#= structName #>StringExtensions { /// /// Create a new struct wrapping a string. /// /// The string to wrap. It must not be null. /// A function to transform and/or validate the string. /// The unwrapped string is passed into the transform function, /// and the transform should return null if the string is not valid, // otherwise the transform should convert the string as needed (eg remove spaces, convert to uppercase, etc). /// A null transform is ignored. /// /// Thrown if the str is null. public static <#= structName #> To<#= structName #>(this string str, Func transform) { return <#= structName #>.New(str, transform); } /// /// Create a new struct wrapping a string. /// /// Thrown if the str is null. public static <#= structName #> To<#= structName #>(this string str) { return <#= structName #>.New(str); } /// /// Create a new nullable struct wrapping a string, or null if the string is null or invalid. /// /// The string to wrap. If is is null or invalid, null is returned. /// A function to transform and/or validate the string. /// The unwrapped string is passed into the transform function, /// and the transform should return null if the string is not valid, // otherwise the transform should convert the string as needed (eg remove spaces, convert to uppercase, etc). /// A null transform is ignored. /// public static <#= structName #>? To<#= structName #>Option(this string str, Func transform) { return <#= structName #>.NewOption(str, transform); } /// /// Create a new nullable struct wrapping a string, or null if the string is null. /// public static <#= structName #>? To<#= structName #>Option(this string str) { return <#= structName #>.NewOption(str); } } }