Jasper and C#


 


The question “Is Jasper useable from c#?” came up on the Jasper forum.

The short answer is – We designed Jasper specifically for CLR languages with late-bound facilities such as VB and IronPython.  C# doesn’t currently support late-bound calls and hence the answer would be no though some aspects of Jasper may still be applicable.

The long answer is a lot more interesting.

Part of the Jasper framework’s functionality provided by the Jasper framework is the generation of  the data classes (representing the underlying database tables and/ or entities) at runtime.  This relieves the developer the burden of writing the data classes themselves or using design time code generation tools.  It also means no deployment cost for the data classes and even allows the database to be changed after the app has been deployed.  A whole lot of goodness for certain types of database apps that don’t want to pay the tax required by most O/R frameworks that exist today and enables a nice iterative, agile development experience.

Since these runtime generated data classes are clr types, one must use a CLR language that supports late binding or use reflection to access members of the data classes.   The latter is very painful and probably more work then actually writing the data classes themselves.

Therefor, Jasper works only with CLR languages that support late binding.  And since we started working on Jasper when the DLR was white board talk, we decided to target Python 1.1 and VB 9 (Orcas versions) – the only CLR languages that supported late binding at the time.

That said, some aspects of the Jasper API can be used from C#.  Let me give a little background of why that is the case by looking at how Jasper allows data class customization.

In Jasper, we wanted a way for users to add the own method/ properties/ fields/ events to the data class generated by Jasper.  To support this, we allowed the user to define a base class.  Then at type generation time, the Jasper runtime would search the app domain to see if a candidate base type exists to derive the new generated type from.  For example, the following type Story would be used as the base type for the runtime generated Jasper data class based on the Stories table:


    Public Class Story


   ‘ Status is not a column in the Stories table


        Private _status As Boolean

        Public Function GetTitle(ByVal title As String) As String

           ‘Truncate the title if it is too long

           If title.Length > 200 Then

               Return title.Substring(0, 199)

           End If

           Return title

        End Function


        Public Function IsStoryActive() As Boolean

           Return _status

        End Function

    End Class


Note, the GetTitle method is an example using the of the GetProperty/ SetProperty naming convention that we use to inject custom methods into the generated property Getter/ Setters.  For more information on this see the Project Jasper overview document included with the CTP release. 

The cool thing about using this base class technique is that the methods or properties in the base class can refer to properties that will be added to the generated derived class based on columns in the underlying database table at runtime.

To allow the user to specify as much (or as little) of the base class as they would like,  the Jasper runtime examines the candidate base type to see if any properties or fields are already are part of the base class.  If that is true, then the runtime does not generate those fields/ properties for the generated data class.  It is even possible to specify abstract properties and have the derived class generate the implementation, for example:

    Public MustInherit Class Story

        Public MustOverride Property Title() As String

        Public MustOverride Property Description() As String

    End Class

So the interesting observation here is when the base class specifies the abstract properties, the properties can then be used in C# without requiring reflection:


   


    abstract public class Story


    {

         abstract public string Title { get; set;} 

         abstract public string Description { get; set; }

         abstract public DateTime? PublishedDate { get; set; }

    }

    

    // can now call

    var stories = myDynamicContext.GetQuery(“Stories”);

    Story myStory = stories[0]; //get first story

    myStory.Title = “New Story Title”;


So it would be possible to call properties of the Story instances as long as they were static declared on the Story base type.   However, we are not particularly pleased with this design and experience.  The new C# feature of automatic properties may be a bit better and we are still evaluating its use in Jasper.

That all said, we are actively working on moving Jasper over to the dynamic language runtime – the freshly announced .Net addition to the runtime designed to extent the CLR for dynamic typed CLR languages (VBX, IronPython, IronRuby).  Based on early analysis it is a strong possibility that we move away from the base class mechanism and support a more dynamic model where data class types (or even specific instances!) can be modified at runtime to allow the user to add their own business logic.

The other consideration with respect to using Jasper in C# is that the autobinding components (AutoDataSource, AutoBinder) – see overview document for more information) included in the Jasper framework.  These do not require late binding and/ or a dynamic language to be utilized.  So, this part of the framework will function in C# as it does in the dynamic languages.  This is possible because the binding protocols are already work in a late bound manner and do not required design types unless on is using the design time support offered by the tools.

Comments (8)

  1. Why don’t you build a BuildProvider for ASP.NET that generates the classes dynamically? That way you don’t need late binding and you can use it from C# in ASP.NET.

  2. aconrad says:

    For a few reasons we don’t use ASP.net build providers:

    1)  We also want to support Avalon and winform apps with the same Jasper API and experience.  

    2)  ASP.Net build providers statically generate code – not dynamically at runtime like Jasper.  So in reality, this would not be a huge improvement over the EDMGen utility currently being shipped as part of the Entity Framework.  

    3)  We are trying to make Jasper a data access API geared toward iterative & agile development.  This means supporting scenarios like changing the database without recompiling the app and working in interactive environments like the Python REPL utility – either of which will work with build providers as they exist today.

  3. Aren’t C# type inference, extension methods and the like enough to implement Jasper’s functionality? Why should a project that uses Jasper have to use a late binding language?

    There are over 30 ORMs and frameworks in the market that don’t have this limitation which use every conceivable method from Dynamic Methods (NHibernate) to Reflection to code generation, that don’t have any language dependencies.

    Furthermore, the agile community is predominantly C# oriented.  By providing a VB only data access API you may annoy the very crowd you are trying to please.

  4. Hi Andrew,

    OK about 1 and 2

    On 3, it’s true, but from the development experience point of view is equivalent (or actually better as you have intellisense) as the compilation is performed at runtime.

    Regards

  5. Steve says:

    // can now call

       var stories = myDynamicContext.GetQuery("Stories");

       Story myStory = stories(0); //get first story

       myStory.Title = "New Story Title";

    This code will not work… stories(0) was probably ment as stories[0] but the stories instance has no type information… So I guess what it ment to be was:

    // can now call

       var stories = myDynamicContext.GetQuery<Story>("Stories");

       Story myStory = stories[0]; //get first story

       myStory.Title = "New Story Title";

  6. aconrad says:

    thanks – fixed the array indexer call.   It is hard constantly switching between languages.

    However, note when you call GetQuery, you don’t need to specify the type T.  We have a non-generic version.

  7. I heard a while back that Project Jasper was discontinued, but the code may be used somewhere in ADO.NET.

    Where can we get some information on this?

    Thanks,

    Jason Kergosien

  8. aconrad says:

    Not that I know of.  We have been waiting for the DLR to mature before proceeding with dynamic languages.