RSCG- part 13 – IFormattable

 

 

name IFormattable
nuget

https://www.nuget.org/packages/AOPMethodsCommon/
https://www.nuget.org/packages/AOPMethodsGenerator/

link http://msprogrammer.serviciipeweb.ro/category/roslyn/
author Andrei Ignat

This will generate code to add IFormattable to any class, based on the properties of the class
 

The code that you start with is


    [AutoMethods(CustomTemplateFileName = "CreateFormattable.txt", template = TemplateMethod.CustomTemplateFile)]                    

    partial class Department

    {

        public int ID { get; set; }

        public string Name { get; set; }

    

    }

    [AutoMethods(CustomTemplateFileName = "CreateFormattable.txt", template = TemplateMethod.CustomTemplateFile)]

    partial class Employee

    {

        public int ID { get; set; }

        public string Name { get; set; }

    

        public Department dep { get; set; }

        

    }


The code that you will use is



    var e = new Employee();

    e.ID = 1;

    e.Name = "Andrei";

    e.dep = new Department();

    e.dep.Name = "IT";

    

    Console.WriteLine(e.ToString("for employee with id = {id} the name is {name} and department is {dep?.Name}", null)); 

    

    e.dep = null;

    

    Console.WriteLine(e.ToString("for employee with id = {id} the name is {name} and department is {dep?.Name}", null));

    

 

The code that is generated is


    [GeneratedCode("AOPMethods", "2021.2.27.640")]                                             

    [DebuggerDisplay(" ID = {ID} Name = {Name} dep = {dep}")]

    partial class Employee: IFormattable{

        public object ValueProperty(string val){

            val = val.Replace("?","");

                if(string.Compare("ID",val,StringComparison.CurrentCultureIgnoreCase)==0) {

                    return this.ID;

                }

                if(string.Compare("Name",val,StringComparison.CurrentCultureIgnoreCase)==0) {

                    return this.Name;

                }

                if(string.Compare("dep",val,StringComparison.CurrentCultureIgnoreCase)==0) {

                    return this.dep;

                }

            throw new ArgumentException("cannot find "+ val);

        }

        

        //adapted from https://haacked.com/archive/2009/01/14/named-formats-redux.aspx/

        private object Eval(string expression,IFormatProvider formatProvider)

        {

            if (expression.Contains("."))

            {

                var splut = expression.Split(".");

                bool canBeNull=splut[0].Contains("?");

                dynamic d = ValueProperty(splut[0]);

                if(canBeNull && d == null)

                    return null;

                for(var i=1; i<splut.Length;i++){

                    canBeNull=splut[i].Contains("?");

                    d=d.ToString("{"+splut[i]+"}",formatProvider);

                    if(canBeNull && d == null)

                        return null;

                }

                return d;

                

            }

    

            return ValueProperty(expression);

    

        }

    

    

        

        public string ToString(string format, IFormatProvider formatProvider)

        {

            if (format == null)

                throw new ArgumentNullException("format");

    

            List<object> values = new List<object>();

            string rewrittenFormat = Regex.Replace(format,

                delegate (Match m)

                {

                    Group startGroup = m.Groups["start"];

                    Group propertyGroup = m.Groups["property"];

                    Group formatGroup = m.Groups["format"];

                    Group endGroup = m.Groups["end"];

    

                    values.Add((propertyGroup.Value == "0")

            ? this

            : Eval(propertyGroup.Value, formatProvider));

    

                    int openings = startGroup.Captures.Count;

                    int closings = endGroup.Captures.Count;

    

                    return openings > closings || openings % 2 == 0

                ? m.Value

                : new string('{', openings) + (values.Count - 1)

                + formatGroup.Value

                + new string('}', closings);

                },

                RegexOptions.Compiled

                | RegexOptions.CultureInvariant

                | RegexOptions.IgnoreCase);

    

            return string.Format(formatProvider, rewrittenFormat, values.ToArray());

        }

    

    }

Example Code: https://github.com/ignatandrei/RSCG_Examples/tree/main/IFormattable

All RSCG

NrBlog Post
1RSCG–part 1
2RSCG- AppVersion–part 2
3http://msprogrammer.serviciipeweb.ro/2021/02/17/rsgc-enum-part-3/
4RSGC-JSON to Class- part 4
5RSGC-Constructor – Deconstructor – part 5
6RSGC – DTO Mapper – part 6
7RSGC – Skinny Controllers- part 7
8RSGC-Builder Design Pattern – part 8
9RSGC- MetadataFromObject – part 9
10RSGC- Dynamic Mock – part 10
11RSCG- Method Decorator – part 11
12RSCG – Curry – Partial function – part 12
13RSCG- part 13 – IFormattable
14RSCG- part 14 – DP_Decorator
15RSCG- part 15 – Expression Generator
16RSCG- part 16 – Many Others
17RSCG- the book
18RSCG–Template Rendering- part 17
19CI Version
20HttpClientGenerator
21Query from database
22AutoRegister
23TinyTypes
24Static2Interface
25AppSettings
26Properties
27
Roslyn Source Code Generators