Click here to Skip to main content
11,720,785 members (69,953 online)
Click here to Skip to main content

Tagged as

A Little Chat About Code Sensible Code Generation

, 9 Apr 2009 CPOL 7.7K 4
Rate this:
Please Sign up or sign in to vote.
At work we all try and do our best to be productive. And as software developers we all probably have to author classes, that follow a familiar pattern. So if like me you are looking to work smart, you will undoubtedly look into code that writes code.This is good in my opinion, code generation can [

At work we all try and do our best to be productive. And as software developers we all probably have to author classes, that follow a familiar pattern. So if like me you are looking to work smart, you will undoubtedly look into code that writes code.

This is good in my opinion, code generation can save a LOT of time. But the cardinal rule of clever code generation is never ever having to touch the generated code once it has been generated. If you do have to make changes by hand to a generated file, its all wrong and the entire process can no longer be trusted.

Now this perplexed me for a while as I had a very real demand to perform some calculations when a property changes. Now this would be cool and could possibly be made part of the generated code if you know about it in advance and have the correct knowledge to instruct your code generator about this in advance. We neither knew about these requirements up front or were able to build enough intelligence into our code generator to deal with this sort of this.

So you can imagine that our business analyst came along and said "when property X changes, use property Y and Z to work out Q". Mmmmm.

This would require me to do something when a property changes, this would mean manually changing my auto generated code. Oh no.

So I had a think about this, and luckily C# being the lovely language that it is has the answers. Partial classes / methods. All we need to do is provide the stubs in the generated code portion and provide hooks that the manually created partial class can use.

Here is an example.

The code generated part

  1:  using System;
  2:  using System.Collections.Generic;
  3:  using System.Linq;
  4:  using System.Text;
  5:
  6:  namespace NiceCodeGenStylee
  7:  {
  8:      public partial class Class1
  9:      {
 10:
 11:          private Int32 number1 = 0;
 12:          private Int32 number2 = 0;
 13:
 14:          /// <span class="code-SummaryComment"><summary></span>
 15:          /// When this method in called the hand cranked 
 16:          /// code should have the implementation
 17:          /// <span class="code-SummaryComment"></summary></span>
 18:          partial void Number1PropertyChanging(
                           IntReportChanges args);
 19:
 20:          /// <span class="code-SummaryComment"><summary></span>
 21:          /// When this method in called the hand cranked 
 22:          /// code should have the implementation
 23:          /// <span class="code-SummaryComment"></summary></span>
 24:          partial void Number1CodePropertyChanged(
                           Int32ItemChanges args);
 25:
 26:
 27:          /// <span class="code-SummaryComment"><summary></span>
 28:          /// When this method in called the hand cranked 
 29:          /// code should have the implementation
 30:          /// <span class="code-SummaryComment"></summary></span>
 31:          partial void Number2PropertyChanging(
                           IntReportChanges args);
 32:
 33:          /// <span class="code-SummaryComment"><summary></span>
 34:          /// When this method in called the hand cranked 
 35:          /// code should have the implementation
 36:          /// <span class="code-SummaryComment"></summary></span>
 37:          partial void Number2CodePropertyChanged(
                           Int32ItemChanges args);
 38:
 39:
 40:          /// <span class="code-SummaryComment"><summary></span>
 41:          /// Number1 property
 42:          /// <span class="code-SummaryComment"></summary></span>
 43:          public Int32 Number1
 44:          {
 45:              get { return number1; }
 46:              set
 47:              {
 48:                  //is it different
 49:                  if(value != number1)
 50:                  {
 51:                      Int32 oldValue = number1;
 52:
 53:                      //what are the changes
 54:                      Int32ItemChanges possibleValueChanges
 55:                          = new Int32ItemChanges(
                                     oldValue, value);
 56:
 57:                      //report the possible change, allows non generated file to 
 58:                      //respond to the change, or cancel it
 59:                      IntReportChanges changes =
 60:                          new IntReportChanges
 61:                          {
 62:                              Values = possibleValueChanges
 63:                          };
 64:                      Number1PropertyChanging(changes);
 65:
 66:                      //if there was no cancellation
 67:                      if (!changes.Cancel)
 68:                      {
 69:                          number1 = value;
 70:                          //report the change, allows non generated file to 
 71:                          //respond to the change
 72:                          Number1CodePropertyChanged(
                                  possibleValueChanges);
 73:                      }
 74:                  }
 75:
 76:              }
 77:          }
 78:
 79:          /// <span class="code-SummaryComment"><summary></span>
 80:          /// Number2 property
 81:          /// <span class="code-SummaryComment"></summary></span>
 82:          public Int32 Number2
 83:          {
 84:              get { return number2; }
 85:              set
 86:              {
 87:                  //is it different
 88:                  if (value != number2)
 89:                  {
 90:                      Int32 oldValue = number2;
 91:
 92:                      //what are the changes
 93:                      Int32ItemChanges possibleValueChanges
 94:                          = new Int32ItemChanges(oldValue, value);
 95:
 96:                      //report the possible change, allows non generated file to 
 97:                      //respond to the change, or cancel it
 98:                      IntReportChanges changes =
 99:                          new IntReportChanges
100:                          {
101:                              Values = possibleValueChanges
102:                          };
103:                      Number1PropertyChanging(changes);
104:
105:                      //if there was no cancellation
106:                      if (!changes.Cancel)
107:                      {
108:                          number2 = value;
109:                          //report the change, allows non generated file to 
110:                          //respond to the change
111:                          Number1CodePropertyChanged(
                                  possibleValueChanges);
112:                      }
113:                  }
114:
115:              }
116:          }
117:
118:
119:      }
120:  }

Where the manually created code part, can use these partial method stubs to do calculations when a property changes or even cancel a changing property based on some condition.

 1:  using System;
 2:  using System.Collections.Generic;
 3:  using System.Linq;
 4:  using System.Text;
 5:
 6:  namespace NiceCodeGenStylee
 7:  {
 8:      partial class Class1
 9:      {
10:          /// <span class="code-SummaryComment"><summary></span>
11:          /// When this method in called the hand cranked 
12:          /// code should have the implementation
13:          /// <span class="code-SummaryComment"></summary></span>
14:          partial void Number2PropertyChanging(
                 IntReportChanges args)
15:          {
16:              if (args.Values.NewValue == 0)
17:              {
18:                  Console.WriteLine(
19:                      "Number2 is invalid value, cancelling");
20:                  args.Cancel = true;
21:              }
22:          }
23:
24:          /// <span class="code-SummaryComment"><summary></span>
25:          /// When this method in called the hand cranked 
26:          /// code should have the implementation
27:          /// <span class="code-SummaryComment"></summary></span>
28:          partial void Number2CodePropertyChanged(
                 Int32ItemChanges args)
29:          {
30:              Console.WriteLine(String.Format(
31:                  "Number2 changed to {0}, doing calcs",
                     args.NewValue));
32:              DoNumberCalcs();
33:          }
34:
35:
36:          /// <span class="code-SummaryComment"><summary></span>
37:          /// When this method in called the hand cranked 
38:          /// code should have the implementation
39:          /// <span class="code-SummaryComment"></summary></span>
40:          partial void Number1PropertyChanging(
                 IntReportChanges args)
41:          {
42:              if (args.Values.NewValue == 0)
43:              {
44:                  Console.WriteLine(
45:                      "Number1 is invalid value, cancelling");
46:                  args.Cancel = true;
47:              }
48:          }
49:
50:          /// <span class="code-SummaryComment"><summary></span>
51:          /// When this method in called the hand cranked 
52:          /// code should have the implementation
53:          /// <span class="code-SummaryComment"></summary></span>
54:          partial void Number1CodePropertyChanged(
                 Int32ItemChanges args)
55:          {
56:              Console.WriteLine(String.Format(
57:                  "Number1 changed to {0}, doing calcs",
                     args.NewValue));
58:              DoNumberCalcs();
59:          }
60:
61:
62:          private void DoNumberCalcs()
63:          {
64:              Console.WriteLine(
65:                  String.Format("Number1 ({0}) + Number2 ({1}) ={2}",
66:                      number1, number2, number1 + number2));
67:          }
68:      }
69:  }

Where these little helper classes are used

 1:  using System;
 2:  using System.Collections.Generic;
 3:  using System.Linq;
 4:  using System.Text;
 5:
 6:  namespace NiceCodeGenStylee
 7:  {
 8:      struct Int32ItemChanges
 9:      {
10:          public readonly Int32 OldValue;
11:          public readonly Int32 NewValue;
12:
13:          public Int32ItemChanges(
                 Int32 oldValue, Int32 newValue)
14:          {
15:              OldValue = oldValue;
16:              NewValue = newValue;
17:          }
18:      }
19:
20:  }
 1:  using System;
 2:  using System.Collections.Generic;
 3:  using System.Linq;
 4:  using System.Text;
 5:
 6:  namespace NiceCodeGenStylee
 7:  {
 8:      class IntReportChanges
 9:      {
10:          public Int32ItemChanges Values { get; set; }
11:          public Boolean Cancel { get; set; }
12:      }
13:  }

And here is a demo of it running

image-thumb6.png

See it all works lovely.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150901.1 | Last Updated 9 Apr 2009
Article Copyright 2009 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid