RecentComments

Comment RSS

Domain Specific Languages with M - Part 1/3 Defining the syntax

by Ioannis 10. April 2010 09:07

Say you are implementing software for a company that rents items. And you are presented with some bizarre and complex logic on the way renting fees are calculated. To be more specific requirements come to you in the following form:

“I want a renting fee scenario where an item for the first month is charged 10$ per day. Then, the same item costs 5$ per week for the next two months. Finally, after this period of three months the fee will be 20$ per month. But this is just one scenario…”

Clearly your inclination will be to go talk to the guy, help him write all his scenarios and then come up with a clever algorithm that calculates the fees and (hopefully) a UI where the guy can add more scenarios and persist them in the database.

Or you can implement a DSL. A DSL that allows somebody to express such complex renting-fee scenarios in an easy to use language. Hopefully this language will offer you more expressiveness and flexibility than a nicely constructed UI. From the moment you realize that renting fees will need requirement analysis, you come up with the following DSL:

 

Scenario (“Monthly”)
    For 1 month charge 10$ per day.
    For 2 months charge 5$ per week.
    Eventually charge 20$ per month.
End

 

Clearly this is something that can be given to the guy and ask him to express his renting fee scenarios using this language. At the time he writes his specs, you have work to do:

 

  • Create a database that stores those scenarios in some form.
  • Implement the algorithm that calculates the fees for any arbitrary scenario you may receive.

 

It all boils down to finding a way to parse the language and express meaningful information from it. How does “M” facilitate this process? As you will see you get a lot of out of the box goodies by implementing this DSL in “M”.

 

 Defining the syntax in M

Open Intellipad and select “DSL Grammar Mode”:

 

 

Create a text file that contains a demo scenario like the one we have written above.  Now go ahead and select “Open File as Input and Show Output”:

 

 

This will split your window in three. On the left you have your demo program in your new DSL. In the middle you write your DSL’ s syntax. On the right you get what “M” understands from your syntax and the demo program. Go ahead and write in the middle (where the syntax goes) the following:

 

module RentingApp
{
    language RentLanguage
    {
        syntax Main=any*;
    }
}

 

That is, you define a module named “RentingApp” which contains the syntax of the language “RentLanguage”. The syntax consists of a single rule that matches everything. The rule says that “Main” contains zero of more occurrences of any character. The moment you write these lines, the framework understands the input language and displays it on the right (Note that the result is a set of single characters):

 

 

 Of course this is of little help. Let’s go and make the syntax more specific by providing the following rules:

 

 

module RentingApp
{
    language RentLang
    {
        interleave whitespace = (" " | "\r" | "\n" | "\t")+;
       
        syntax Main=RentCharge*;
        syntax RentCharge="Scenario" "(" ChargeScenarioName ")" ChargeRules "End";
        syntax ChargeRules=(ChargeRule ".")*;
        token ChargeRule= "For" !('.')+ | "Eventually" !('.')+;
       
        syntax ChargeScenarioName=QuotedIdentifier;
        token QuotedIdentifier = '"' !('\r' | '\n' | '"')+ '"';
    }
}

 

The first thing to note is the directive “interleave…” which tells that our language does not take into consideration any spaces or returns or tabs.

The <Main> part consists of one or more <RentCharge> parts. Each <RentCharge> part begins with the word “Scenario“ and an opening “(“, has a <ChargeScenarioName> part followed by a closing “)”, then has a <ChangeRules> part and finally ends with the word “End”.

The <ChargeScenarioName> part is a <QuotedIdentifier> which matches one or more characters within quotes apart from “\r” and \n”.

The <ChargeRules> part consists of zero or more <ChargeRule> parts which end with “.”.

The <ChargeRule> parts start with the word “For” and then matches everything except the “.” or start with “Eventutally” and then anything except “.”.

This is practically how we construct the syntax of the DSL. The full syntax supporting the language we are building for the renting scenarios is as follows:

 

module Renting
{
    language RentLanguage
    {
        interleave whitespace = (" " | "\r" | "\n")+ | Comment;
       
        syntax Main= Charges+;
        syntax Charges=ChargeStartToken "(" ChargeName ")" ChargeBody ChargeEndToken;
        syntax ChargeBody=ChargeRule+;
        syntax ChargeRule=ForToken PeriodAmount Period ChargeToken CurrencyAmount CurrencyToken "per" Period "."
                         |EventuallyToken ChargeToken CurrencyAmount CurrencyToken PerToken Period ".";
        token PeriodAmount=('0'..'9')+;
       
        token Period="week"|"weeks"|"month"|"months"|"days"|"day"|"year"|"years";
        token CurrencyAmount=('0'..'9')+ DecimalSeparator ('0'..'9')* | ('0'..'9')+;
        token ChargeName=QuotedIdentifier;
        token DecimalSeparator=",";
        token ChargeStartToken="Scenario";
        token ChargeEndToken="End";
        token ForToken="For";
        token EventuallyToken="Eventually";
        token CurrencyToken="$";
        token ChargeToken="charge";
        token PerToken="per";
        token Comment = "//" !("\r" | "\n")+;
        token QuotedIdentifier = '"' !('\r' | '\n' | '"')+ '"';
    }
}

 

As you can see we do not hard code any of the literals of the language (such as “Scenario” etc) within the syntax rules. We do that to be able to easily change the spoken language of our DSL (for example from English to Greek). The syntax you see above recognizes all the possible sentences that will be written for the renting scenario and as you may have noticed from the first rule, it accepts more than one renting scenarios at once.

You can download the aforementiond grammar for the English language here and a little different version for the Greek langauge here.

In the next post we will decorate our DSL with attributes and create productions to alter the output of the DSL parser.

 

 

Shout it

kick it on DotNetKicks.com

Tags:

.NET

NHibernate, PropertyChanged event and WPF

by Ioannis 28. August 2009 15:30

A typical implementation of an entity that supports the INotifyPropertyChanged interface for WPF Binding is for example as follows:

public class Detail:INotifyPropertyChanged
{

    private long _iD;
    public virtual long ID
    {
        get { return _iD; }
        set { _iD = value;
              if (PropertyChanged != null)
                  PropertyChanged(this, new PropertyChangedEventArgs("ID"));}
    }
 
    private string _line1;
    public virtual string Line1
    {
        get { return _line1; }
        set { _line1 = value;
              if (PropertyChanged != null)
                  PropertyChanged(this, new PropertyChangedEventArgs("Line1"));}
    }
 
    private string _line2;
    public virtual string Line2
    {
        get { return _line2; }
        set { _line2 = value;
              if (PropertyChanged != null)
                  PropertyChanged(this, new PropertyChangedEventArgs("Line2"));}
    }
 
    private Entity _relatedEntity;
    public virtual Entity RelatedEntity
    {
        get { return _relatedEntity; }
        set { _relatedEntity = value;
              if (PropertyChanged != null)
                  PropertyChanged(this, new PropertyChangedEventArgs("RelatedEntity"));}
    }
    public virtual event PropertyChangedEventHandler PropertyChanged;

 

Class Detail supports the INotfiyPropertyChanged interface and is ready for data-binding in a WPF Window. Try to bind the properties "Line1" and "Line2" to TextBoxes in a WPF Window and soon you will realize that if you load the entity from a database using NHibernate by:

 

  • Load<Detaill>(id) : The PropertyChanged events are ignored by WPF
  • Get<Detail>(id): The PropertyChanged events are processed as expected by WPF

This behaviour is due to the fact that Load returns a proxy object while Get doesn't. More seriously though if in the same window you want to bind to properties of the property RelatedEntity (eg RelatedEntity.Description)  which is instantiated by a many-to-one relationship and you use "Lazy-Loading", you will have a proxied Entity object and the PropertyChanged event will be ignored as before.

It seems that when a proxy is involved, ProperyChanged events are ignored by WPF.The obvious choice is to always use Get and disable "Lazy-Loading" which is of course something that usually is not an option.

But there seems to be another solution:

The reason the problem occurs has to do with the fact that WPF expects a PropertyChanged event from the proxy object and gets it from the actual object. This can be better explained with the following figure:

 

When the property "Line1" is changed(Bottom), a PropertyChanged event is generated that goes through the proxy to the WPF TextBox. WPF ignores the event since it is databound to the _detailProxy object and not to the _detail object. In other words it awaits events of the form PropertyChanged (_detailProxy,"Line1") and not PropertyCahnged (_detail,'Line1").

The solution is to extend the proxy implementaion so that it takes the resoonsibility of notifying WPF when a property is changed. We will keep the original implementation of the entity as is to support the NotifyPropertyChanged mechanism when NHibernate is not involved in the object creation process and we will create a new Interceptor for the proxy to support the same functionality when NHibernate creates the object for us. Moreover the process will be as non invasive as possible in case in future implementations of NHibernate the issue is resolved.

We create a new file called NotifyProprtyChangedInterceptor.cs and first, we add a bunch of .using statements (make sure you reference the appropriate libraries):

using System.ComponentModel;
using NHibernate.Proxy.Poco.Castle;
using System.Reflection;
using NHibernate.Engine;
using NHibernate.Type;
using Castle.Core.Interceptor;
using Castle.DynamicProxy.Generators;
 
using System.Collections;
using NHibernate.Proxy;
using NHibernate;

We implement in it the following class which will create our extended proxy:

// We override this class implementation to handle the proxy creation ourselves. We
// need to specify our own Interceptor when a method of our entity is called.
public class DataBindingNotifyPropertyProxyFactory : CastleProxyFactory
{
    public override INHibernateProxy GetProxy(object id, ISessionImplementor session)
    {
        // If it is not a proxy for a class do what you usually did.
        if (!IsClassProxy) return base.GetProxy(id, session);
 
        try
        {               
            CastleLazyInitializer initializer = new DataBindingInterceptor(EntityName,PersistentClass, id,
                       GetIdentifierMethod, SetIdentifierMethod,ComponentIdType, session);
           
            // Add to the list of the interfaces that the proxy class will support the INotifyPropertyChanged interface.
            // This is only needed in the case when we need to cast our proxy object as INotifyPropertyChanged interface.
            ArrayList list = new ArrayList(Interfaces);
            list.Add(typeof(INotifyPropertyChanged));
            System.Type[] interfaces = (System.Type[])list.ToArray(typeof(System.Type));
 
            //We create the proxy (for the class, Interfaces Supported, Interceptor to use)
            object generatedProxy = DefaultProxyGenerator.CreateClassProxy(PersistentClass, interfaces, initializer);
 
            initializer._constructed = true;
            return (INHibernateProxy)generatedProxy;
        }
        catch (Exception e)
        {
            log.Error("Creating a proxy instance failed", e);
            throw new HibernateException("Creating a proxy instance failed", e);
        }
    }
}

In the same file we implement the interceptor that is used by the proxy:

public class DataBindingInterceptor : CastleLazyInitializer
 {
     private PropertyChangedEventHandler subscribers = delegate { };
 
     public DataBindingInterceptor(String EntityName,Type persistentClass, object id,MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod,IAbstractComponentType aType, ISessionImplementor session)
         : base(EntityName,persistentClass, id, getIdentifierMethod, setIdentifierMethod,aType, session)
     {
     }
 
     public override void Intercept (IInvocation invocation)
     {
         // WPF will call a method named add_PropertyChanged to subscribe itself to the property changed events of
         // the given entity. The method to call is stored in invocation.Arguments[0]. We get this and add it to the
         // proxy subscriber list.
         if (invocation.Method.Name.Contains("PropertyChanged"))
         {
             PropertyChangedEventHandler propertyChangedEventHandler = (PropertyChangedEventHandler)invocation.Arguments[0];
             if (invocation.Method.Name.StartsWith("add_"))
             {
                 subscribers += propertyChangedEventHandler;
             }
             else
             {
                 subscribers -= propertyChangedEventHandler;
             }
         }
        
         // Here we call the actual method of the entity
         base.Intercept(invocation);
 
         // If the method that was called was actually a proeprty setter (set_Line1 for example) we generate the
         // PropertyChanged event for the property but with event generator the proxy. This must do the trick.
         if (invocation.Method.Name.StartsWith("set_"))
         {              
             subscribers(invocation.InvocationTarget, new PropertyChangedEventArgs(invocation.Method.Name.Substring(4)));
         }
     }
 }

Finally we implement the creator of the proxy factory in the same file:

public class ExtendedWithNotifyProxyFactoryFactory :NHibernate.Bytecode.IProxyFactoryFactory
{
    public IProxyFactory BuildProxyFactory()
    {
        return new DataBindingNotifyPropertyProxyFactory();
    }
}

And we are done! To use the new interceptor, when inititalizing NHibernate we add the following (line needed in red color):

Configuration cfg = new Configuration();
cfg.AddAssembly("NHibernateTests");
cfg.Properties[NHibernate.Cfg.Environment.ProxyFactoryFactoryClass] = typeof(ExtendedWithNotifyProxyFactoryFactory).AssemblyQualifiedName;
_sessionFactory = cfg.Configure().BuildSessionFactory();

Now we can work with proxies and WPF receives the appropriate PropertyChanged events when properties change. Whenever we want to disable this functionality we just omit the line that adds it in the configuration.

If you just need to grab the code and keep working download the following .cs file, add it to your project, add the References and the configuration in the previous paragraph (in red) and you are good to go:

NotifyPropertyChangedInterceptor.zip

This solution-code was based and insipired by the following articles:

Castle Dynamic Proxy tutorial by Krzysztof Koźmic
Extending NHibernate Proxies by Ayende Rahien
The discussion started by Arthur Dorochowicz

kick it on DotNetKicks.com

Shout it

Tags:

.NET | WPF

Timers in WPF

by Ioannis 31. July 2009 07:44

There are times when you need a  task to execute periodically. There are two ways of achieving this:

  • Use the System.Windows.Threading.DispatcherTimer
  • Use the System.Threading.Timer

Say now that you want to implement a class the executes DoSomething() periodically and also informs through a delegate to whoever listens whent the execution is performed. The class for DispatcherTimer is as follows:

public class DTimer
{
    private DispatcherTimer timer;
    public event Action<int> DoSomething;
 
    private int _timesCalled = 0;
 
    public DTimer()
    {
        timer=new DispatcherTimer();
    }
    public void Start(int PeriodInSeconds)
    {
        timer.Interval = TimeSpan.FromSeconds(PeriodInSeconds);
        timer.Tick += timer_Task;
        _timesCalled = 0;
        timer.Start();
    }
 
    public void Stop()
    {
        timer.Stop();
    }
    private void timer_Task(object sender, EventArgs e)
    {
        _timesCalled++;
        DoSomething(_timesCalled);
 
    }
}

The same functionality for Timer is provided by the class below:

 

public class TTimer
{
 
    private Timer timer;
    public event Action<int> DoSomething;
    private int _timesCalled = 0;
 
    public TTimer()
    {}
    public void Start(int PeriodInSeconds)
    {
        timer = new System.Threading.Timer(timer_Task, null, 0,
        PeriodInSeconds*1000);
    }
    public void Stop()
    {
        timer.Dispose();
    }
    private void timer_Task(object State)
    {
        _timesCalled++;
        DoSomething(_timesCalled);
    }
}
Is there any difference? Well one important one is the fact that DoSomething() in the case of the DispatcherTimer is called in the same thread as the application while DoSomething() in the case of Timer is called in a new thread that was created for the timer. The two important implications of this are:
  • If DoSomething() manipulates GUI components then with the Timer you need to use: this.Dispatcher.Invoke((Action)delegate { //GUI RELATED CODE HERE} since you cannot access GUI controls from a different thread directly. With DispatcherTimer you do not need to do that.
  • If DoSomething() performas a time-consuming task, then the GUI will freeze in the case of the DispatcherTimer. In the case of the Timer it won't since the long methos is executed in a different thread

kick it on DotNetKicks.com

Shout it

Tags:

.NET | WPF

Powered by BlogEngine.NET 1.5.0.7

Programming Blogs - BlogCatalog Blog Directory Add to Technorati Favorites

MVP Award

Ioannis Panagopoulos





This blog is using BlogEngine.Net and is hosted in the hoster below. I have not experienced any problems installing BlogEngine.Net in the host and I am satisfied with the host's response times. Therefore I recommend it.


DiscountASP Add