Rhino Generators
Like I said, I got envious from the Eleutian guys, and I decided to try to implement a very simple task with code preprocessing. After a small false start (choose the wrong code parser), I was able to come up with a preprocessor that could take this:
        [PerformanceCounterCategory("TestFoo")]        
        public abstract class Performance
        {        
               [PerformanceCounter(PerformanceCounterType.NumberOfItems64)]
               public abstract PerformanceCounter TotalItems { get; }        
}
And transform it to something like this:
        public class PerformanceDerived : Performance {        
                    
            private HandleSetup _setup = new HandleSetup();        
                    
            private System.Diagnostics.PerformanceCounter _TotalItems =
                          new System.Diagnostics.PerformanceCounter("TestFoo", "TotalItems");        
                    
            public virtual HandleSetup Setup {        
                get {        
                    return this._setup;
                }        
            }        
                    
            public override System.Diagnostics.PerformanceCounter TotalItems {        
                get {        
                    return this._TotalItems;
                }        
            }        
                    
            public class HandleSetup {        
                        
                public virtual void Run() {        
                    if (System.Diagnostics.PerformanceCounterCategory.Exists("TestFoo")) {        
                        System.Diagnostics.PerformanceCounterCategory.Delete("TestFoo");        
                    }        
                    System.Diagnostics.CounterCreationDataCollection counters =
                              new System.Diagnostics.CounterCreationDataCollection();        
                    System.Diagnostics.CounterCreationData TotalItems_Counter =         
                              new System.Diagnostics.CounterCreationData();        
                    TotalItems_Counter.CounterName = "TotalItems";        
                    counters.Add(TotalItems_Counter);        
System.Diagnostics.PerformanceCounterCategory.Create("TestFoo", "",
                              System.Diagnostics.PerformanceCounterCategoryType.SingleInstance, counters);
                }        
            }        
}
Which means that I can the do this:
        [PerformanceCounterCategory("TestFoo")]        
        public abstract class Performance
        {        
               static PerformanceDerived instance = new PerformanceDerived();        
                
               public static PerformanceDerived Instance        
               {        
                      get { return instance; }        
               }        
                
               [PerformanceCounter(PerformanceCounterType.NumberOfItems64)]
               public abstract PerformanceCounter TotalItems { get; }        
}
And now I can get:
        Performance.Instance.Setup.Run();//init the counters        
        Performance.Instance.TotalItems.Increment();//use the counters    
The main advantage here is that I can sometimes reach to a high number of counters, and it is annoying to try to manage them independently.
At the moment I am having issues trying to decide how I should expose this, though. There are two options:
- MsBuild Task - Simple & easy, won't run each time that I run the file, will run as part of the build.
- VS Custom Tool - A bit hard to developer, much harder to deploy, will not run as part of the buiild but will run whenever I change the file.
 

Comments
+1 msbuild task!
Comment preview