posts - 9, comments - 13, trackbacks - 0

My Links

News

Archives

Image Galleries

About Me

Extending autogenerated proxy entities

When you add a WCF service referencein your Silverlight project you get for free a powerful autogenerated proxy: collections are ObservableCollection based, even the entities have already implemented the FireNotification on the set method ( it’s a good exercise to make a “go to definition” and explore the autogenerated classes code).
All this is great but… what happens if you need to extend an autogenerated entity? Let’s say I have the following scenario:
-          A service provides me with a list of expected sales per quarter by product.
-          I display this result on a grid.
-          Now as a requirement I need to:
o   Add an extra column to the grid showing the totals by product.
o   The expected sales entries are editable so if a given user introduces a new figure the totals by product associated cell should be automatically recalculated.
o   Add a validation to the expected sales fields, negatives values are not allowed.
To do this we could try to modify the autogenerated clasess but each time we need to refresh the service reference we would lose our changes,  what can we do?
-          Create your own set of entity classes on the client side: I don’t like that approach, I’m to lazy to write all that plumbing, maybe for some scenarios could be a good idea.
 
-          Create a new class that inherits from the entity class: still some work to do, castings…
 
-          Create a partial class that extends the current entity: that’s my favorite, I only need to add a partial class definition and add the new properties and validations that I need.
Let’s  solve the challenges that we are facing using the third approach.
First, let’s say that our autogenerated entity class looks something like:
   
public partial class EntitySalesForecast : object, System.ComponentModel.INotifyPropertyChanged
{
       
        private double SalesQ1Field;
       
       
       
        [System.Runtime.Serialization.DataMemberAttribute()]
        public double SalesQ1 {
            get {
                return this. SalesQ1Field;
            }
            set {
                if ((this. SalesQ1Field.Equals(value) != true)) {
                    this. SalesQ1Field = value;
                    this.RaisePropertyChanged("SalesQ1");
                }
            }
        }
 
                 // (…) Sample implemetation for Q2, Q3, Q4…
       
    }
 
 
For the “Add extra totals columns” requirement let’s create the partial class (same name as the autogenerated proxy class) and add a new property that just performs the sum calculations (this will extend our proxy generated class without losing changes when refreshing the service reference):
    public partial class EntitySalesForecast
    {
        public double TotalSales
        {
            get
            {
                return (SalesQ1 + SalesQ2  + SalesQ3 +` SalesQ4);
            }
 
        }
 
    }
 
We have the totalSales available to be binded and displayed by the grid.
Now comes a trickier part, we need to refresh the totals field whenever a Quarter entry changes, we cannot directly add a call to RaisePropertyChanges on the Totals sales for each quarter property because each quarter property been already implemented by the proxy, what we are going to do is to keep on extending the newly created partial class, and create a new property per quarter (for instance if we have Quarter1 let’s call it Quarter1Bindable) that would wrap the Quarter1 property and implement the additional functionality that we need… then on the presentation layer we will replace the old QuarterX binding with the new QuarterXBindable.
public partial class EntitySalesForecast : object, System.ComponentModel.INotifyPropertyChanged
{
     // (…) Add to the previouls created partial class a property per quarter
     public double SalesQ1 _ToBind
        {
            get
            {
                return SalesQ1;
            }
 
            set
            {
                if ((SalesQ1.Equals(value) != true))
                {                
   SalesQ1Field = value;
   // DataGrid cell binding to this field will get a notification to refresh the value displayed
                    this.RaisePropertyChanged("SalesQ1_ToBind");
                    // Changes in a month entry... TotalSales calc field must be refreshed as well
                    this.RaisePropertyChanged("TotalSales");
                }
            }
        }
     // (…)
}
By doing this we kepp all the logic of the original property and expose a new property to the grid that will make the refresh totals calls whenever the user changes an entry.
Now that we have implemented this trick, implementing the “sales cannot be below zero” it’s easy just add the functionality to the QuarterXBindable:
        public double SalesQ1 _ToBind
        {
            get
            {
                return SalesQ1;
            }
 
            set
            {
                if ((SalesQ1.Equals(value) != true))
                {
                    // Validations, exception will be handled by SL Error handling Arch (validation)
                    if (value < 0)
                    {
                        throw new Exception("Sales amount cannot be naegative.");
                    }
 
 
   SalesQ1Field = value;
   // DataGrid cell binding to this field will get a notification to refresh the value displayed
                    this.RaisePropertyChanged("SalesQ1_ToBind");
                    // Changes in a month entry... TotalSales calc field must be refreshed as well
                    this.RaisePropertyChanged("TotalSales");
                }
            }
        }
 
Again… keep the original quarter property as it is and extend functionality wrapping it up (of course in the grid you have to bind this new property).
 

Print | posted on Saturday, July 11, 2009 2:07 PM |

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification:
 
 

Powered by: