Building an MVVM framework for both .Net and .Net CF

by Tom 20. May 2010 14:21

Introduction

As you might allready know, I am maintaining a .Net CF application for one of my customers. Unfortunately, the design of the app is a total disaster, and maintaining it is actually a living hell. Fortunately however, my client decided to order a complete rewrite, which I started today. This post will not contain the sourcecode (as it is a proprietary app), but rather explain the guts of the underlying architecture and some info about the design decisions used.

Maybe I will release some of the reusable components in the future under open source, but I am not quite sure yet...

 

Yet another framework ?

Actually, yes !! My main concern about this app framework is keeping it lightweight, flexible, ultraportable and easy to use. By ultraportable I mean that the app should both run on the default .Net, as well as on the Compact Framework, without recompilation.

Since no framework known to me meets my criteria, I decided to get started on yet another framework.

The main design decisions are heavily based on my previous experiences with MvcExtensions, my other framework, as well as a very inspiring and well-know lecture by Rob Eisenberg: "Build your own MVVM framework".

 

Service tools

I have written and implemented the following interfaces which help me in developping the app.

A simple IOC container interface that looks like this


public interface IIOC
{
  T Resolve<T>();
  T Resolve<T>(string name);
  object ResolveObject(string TypeName);
  object ResolveObject(string name,string TypeName);
}


And to register something into the container I have the following methods:


  T Register<T>(T instance);
  T Register<T>(string name,T instance);
  T Register<T>(Func<IIOC,T> factory);
  T Register<T>(string name,Func<IIOC,T> factory);

Next to this I also implemented a lightweight AutoMapper, which I use for just about everything:


public interface IMapper
{
  public void Map(object source,object destination);
}


And again, the implementation allows me to register some mappings using the following function:

    void Register<TSource,TDestination>(Action<TSource,TDestination,IMapper> map);

Next to this I also created a class called ActionResult (looks familiar, doesn't it ;) ).


{
  public object Viewmodel {get;set;}
  public ActionLink Redirect {get;set;}
  public bool Terminate {get;set;}
}

Allthough I have to say that I still have to implement the ActionLink class.

Glueing everything together

Everything you have read so far might seem awfully familiar to some people, which is a good thing imho. But having these tools available is still not the same as having an app framework, or is it ?

Actually, it is almost; my main focus is in the convention-based Model-View-ViewModel approach, which allows me to have controller actions like this:


public class MainController
{

   IMapper sMap;
   IOrderService sOrder;
   IViewModelResolver sVMResolver

   public MainController(IMapper sMap, IOrderService sOrder,IViewModelResolver sVMResolver)
   {
      this.sMap = sMap;
      this.sOrder = sOrder:
   }

   public ActionResult Index()
   {
      var vm = sVMResolver.Resolve<VMIndex>();
      sMap.Map(sOrder.GetOrders(),vm);
      return new ActionResult() { Viewmodel=vm };   
   }
}

Which should also look very familiar !!!

.... in a single form

Now, we have an ActionResult which contains a model, how do we know which form to show ??? It is quite simple : I use a convention. All my Viewmodels start with the letters "VM", and all my views (winforms usercontrols) end with the word "View".

I use a veiwmodel-first approach, i.e. based on my viewmodel, I choose which view to show. This looks like the best approach to me...

I have one Form named MainForm, which contains the following property:


object _Viewmodel;

public object Viewmodel
{
  get
  {
     return _Viewmodel;
  }
  set
  {
    if (_Viewmodel == value)
      return;
     _Viewmodel = value;    
    var t = this.Namespace+"."+_Viewmodel.GetType().Name.Substring(3)+"View";
    var vw = IOC.ResolveObject(t) as UserControl; 
    this.SuspendLayout();
    this.Controls.Clear();
    sMapper.Map(_Viewmodel,vw);
    this.Controls.Add(vw);
    foreach (var prop in _Viewmodel.GetType().GetProperties())
    {
       var ctrl = vw.Controls.Where(x=>x.Name==prop.Name).FirstOrDefault();
       if (ctrl==null) continue;
       sMapper.Map(prop.GetValue(_Viewmodel,null),ctrl));
    }
    foreach (var meth in _Viewmodel.GetType().GetMethods().Where(x=>x.Name.StartsWith("On"))
    {
        // do something similar for the methods; bind them to the corresponding actionlinks
    }
    this.ResumeLayout();
  }
}

And then my main loop will look something like this (not implemented yet):


void Run()
{
    var frm = new MainForm();
    var ar = new ActionResult() {Redirect=new Redirect<MainController>(x=>x.Index())};
    while (!ar.Terminate)
    {
       if (ar.Redirect!=null)
         ar = InvokeActionLink(ar.Redirect);
      else   
      {
         frm.Model = ar.Model;
         ar = WaitForActionResult(frm);
      }
    }
}

Conclusion

While the framework is not yet complete, this is the way I am going to implement the whole thing... If you have any suggestions or comments please do let me know what you think !!!

Bookmark and Share

Tags: , , , , , , ,

CodeProject | Development

Override interface mappings and creata a generic entity version filter

by Tom 20. April 2010 15:02

Introduction

For one of my customers I needed to have some kind of versioning for a whole bunch of entities on my database. Since I use my very own MvcExtensions framework, I wanted to include a functionality which would automatically filter all entities based on this interface :


    public interface IVersionAware
    {
        string Version { get; set; }
    }

In short, I only want to get the entities of the current version through my repository. This interface would then automaticly imply that all data could be filtered by setting a version filter.

I took me quite some time, but spending a weekend at the Dutch coast cleared my mind a bit, and after the weekend I managed to get it working...

The void (tm)

 

Hit the road, Jack !!

Ok, so how can we do this ?

In MvcExtensions I map my domain classes to my database in the following way :


    public class MyDomainDefinition: IDomainDefinition
    {
        public MyDomainDefinition() { }

        public Assembly DomainAssembly
        {
            get { return typeof(Model.Kit).Assembly; }
        }

        public DomainType GetDomainType(Type t)
        {
            if (t.Namespace==typeof(Model.Kit).Namespace)
                return DomainType.Class;
            else
                return DomainType.None;
        }

        //if !=null write mapping files to disk
        public string WriteHbmFilesToPath
        {
            //get { return @"c:\tmp"; }
            get { return null; }
        }
    }

This might look quite simple, but it is an extensive abstraction layer over fluent nhibernate which takes away most of the complexity, and adds a lot of functionality (bitmap storage, multilingual fields to name a few).
After looking around for some info on the net about filtering using fluent nhbernate, I found a solution: one could define a system-wide filter using the following Filterdefinition and mapping.ApplyFilter :


    public class VersionFilter : FilterDefinition
    {
        public static readonly string FILTERNAME = "MyVersionFilter";
        public static readonly string COLUMNNAME = "Version";
        public static readonly string CONDITION = COLUMNNAME + " = :" + COLUMNNAME;

        public VersionFilter()
        {
            WithName(FILTERNAME)
              .WithCondition(CONDITION)
              .AddParameter(COLUMNNAME, NHibernateUtil.String);
        }

        public static void Enable(NHibernate.ISession session, string version)
        {
            session.EnableFilter(FILTERNAME).SetParameter(COLUMNNAME, version);
        }

        public static void Disable(NHibernate.ISession session)
        {
            session.DisableFilter(FILTERNAME);
        }
    }

And this would be the code to map it for some class.


automapping.Override<SomeClassImplementingIVersionAware>(
  mapping=>
  {
    mapping.Id(x=>x.Id);
    mapping.Map(x=>x.Version).Column(VersionFilter.COLUMNAME);
    mapping.ApplyFilter<VersionFilter>();
  }

Since I do not want to call this override for each class implementing IVersionAware, I decided to create a workaround. I spent quite some time in trying to implement this, until I noticed why my workaround was not working: there was a (small bug) in the fluentnhibernate framework.
So I forked fluentnhibernate, fixed the bug, and sent a pull request to the fluentnhibernate guys, and Paul Batum reported to me that my bugfix will be integrated into the next merge, together with some unit tests. For now, you can get the fixed sourcecode from my github version.

... And don't you come back no more....

So, after fixing this, I could get to work again. Since I first tried using IAlterations and Overrides for fluent nhibernate, but all were failing due to the bug, I finally got to this code (which worked after I fixed the bug in fluent nhibernate):


    public static class AutoPersistenceModelExtensions
    {
        public static AutoPersistenceModel OverrideInterface<I,C>(this AutoPersistenceModel model
            , IEnumerable<Type> MyTypes)
            where C:IInterfaceMap<I>,new()
        {
            var modeloverride = model.GetType().GetMethod("Override");
            var interfacemap = new C();
            var cm = typeof(C).GetMethod("Map");
            foreach (var t in MyTypes.Where(x => typeof(I).IsAssignableFrom(x)))
            {
                var act = cm.MakeGenericMethod(t).Invoke(interfacemap,null);
                modeloverride.MakeGenericMethod(t).Invoke(model, new object[] { act });
            }
            return model;
        }
    }

    public interface IInterfaceMap<I>
    {
        Action<AutoMapping<T>> Map<T>() where T:I;
    }

This extension method allows you to override the mappings for interface fields in a very simple way; here is the example for the IVersionAware interface:


    public class VersionAwareInterfaceMap : IInterfaceMap<IVersionAware>
    {
        public Action<AutoMapping<T>> Map<T>() where T : IVersionAware
        {
            return mapping =>
                {
                    mapping.Map(x => x.Version).Column(VersionFilter.COLUMNNAME);
                    mapping.ApplyFilter<VersionFilter>();
                };
        }
    }

And in the MvcExtensions database bootstrapper, I would call this :


        protected Database(IPersistenceConfigurer pcfg, IDomainDefinition mappings)
        {
             // some stuff deleted because it is not relevant here
            var cfg = Fluently.Configure()
                .Database(pcfg)
                .Mappings(m => {
                    var am1 = AutoMap.Assembly(mappings.DomainAssembly)
                        .Where(t => clsmaps.Contains(mappings.GetDomainType(t)))
                        // some stuff deleted because it is not relevant here
                        );
                    var types = mappings.DomainAssembly.GetTypes().Where(x =>
                                typeof(IVersionAware).IsAssignableFrom(x) &&
                                mappings.GetDomainType(x) != DomainType.None);
                    if (types.Count()>0)
                    {
                        am1.OverrideInterface<IVersionAware,VersionAwareInterfaceMap>(types);
                        am1.Add(new VersionFilter());
                    }
                        // some stuff deleted because it is not relevant here

                })
                .BuildConfiguration();
            // some stuff deleted because it is not relevant here
        }

... No more ....

In order to filter my data I would call this :


VersionFilter.Enable(sUnitOfWork.Session,"v1.3.2");

And disabling it again goes like this :


VersionFilter.Disable(sUnitOfWork.Session);

That's all there is to it; all entities implementing the IVersionAware interface will be automatically filtered if you do set the filter....

For a full version you can check out the sourceode over at github.

If you have any questions or remarks, do not hesitate to post them...

Enjoy

Bookmark and Share

Tags: , , , , , , ,

CodeProject | Development | Howto | News

Major update for MvcExtensions

by Tom 12. April 2010 07:28

It has been a while, but I finally managed to push a major upgrade to MvcExtensions; this is the change list:

    * Upgraded spark for MVC RC2
    + Extra string operators for MyText
    + Added abstract model for Joe Celko's NestedSet
    + Added Dynamic SQL (text sorts etc)
    + Added HttpContextBoundObject
    * Improved & extended FluentNhibernate/Database
    + Added Fluentnhibernate TextAlteration for mytext field length in db
    * Improved SetCultureLanguageAttribute
    + Added a class SetCultureHelper for temporary changing language
    + Added IEnumerableHelper extensions for Page & Paging
    + Added helper for building jQuery jqGrid models
    * Bugfixed MyTextModelBinder
    * Improved MvcExtensionsModule

This application framework has allready been used for 2 custom customer applications, and I have to say that it made my development quite successfull.

I have to admit that the documentation is still lacking a lot, but there is a sample project included.

As always, you can download the code here :

http://github.com/ToJans/MVCExtensions

 

Bookmark and Share

Tags: , , ,

Development

"Var keyword is for JavaScript" - about using the var keyword & other coding guidelines

by Tom 31. March 2010 04:28

Introduction

Today I was reading an article on Codeproject, and I was really astounded by the way some people rate articles and give comments...

It was an article about someone who had implemented a simple service locator which contained the following code sample :


using System;
using CuttingEdge.ServiceLocation;
using Microsoft.Practices.ServiceLocation;

public class Global : System.Web.HttpApplication
{
  protected void Application_Start(object sender, EventArgs e)
  {
     // 1. Create a new Simple Service Locator container
     var container = new SimpleServiceLocator();

     // 2. Configure the container

     // Register a delegate that will create a new
     // instance on each call to GetInstance.
     container.Register<ISamurai(() =>
     {
        var weapon = ServiceLocator.Current .GetInstance();
        return new Samurai(weapon);
      });

      // Register a single object instance that always
      // be returned (must be thread-safe).
      container.RegisterSingle(new Katana());

      // 3. Register the container to the Common Locator
      ServiceLocator.SetLocatorProvider(() => container);
    }
}

Which seems quite obvious to me. Since I noticed a comment titled 'my vote of 2', I was curious why this article would be voted such a low score (2 out of 5). I checked the comment and I was astounded:

Please note: the keyword "var" is supposed to be used with anonymous types. You should not use it for anything else. Otherweise please start
programming java script

Who cares ?

Actually, I do.

Since I could not resist I posted the following comment:

Ahum... there have been numerous issues about this, but in general it should not pose a problem, because it is quite clear what it's intentions are at the beginning; i.e. :

var sl = new SimpleServiceLocator();



Is not really more obvious then :

SimpleServiceLocator sl = new SimpleServiceLocator();



In fact, the information in there is the same, but the second one is more verbose, so every person in his right mind would opt for the first alternative.
This might be different if you use a function which does not directly expose the return type in the function name; i.e. :

var x = SomeFunction(y,z);



This is considered bad practice by most.

This one is not :

var myservice = sl.Resolve<IMyService>();



Because the initialization contains enough obvious info to give pointers to the var's type.

So, if this is the only reason why you are giving a 2 (the author has obviously invested quite some time in this article), then you might need to start doing some JavaScript yourself

 

After tweeting about this, I had an interesting conversation with @JacoPretorious about this, who says he uses var everywhere, but pays more attention to variable names.

While I understand what he means, IMHO variable names should not infer the type, only the meaning of the content if necessary.

I personally think there is nothing wrong with using single letters as variable names, as long as the intent is obvious. This is an example that is perfectly valid imho :


public bool InvalidateCustomer(int CustomerId)
{
  var c = sRepo.GetById<Customer>(CustomerId);
  if ( c.Orders.Where(o=>o.PaymentReceivedOn==null).Any())
    return false;
  c.Valid=false;
  sRepo.SaveOrUpdate(c);
  sUOW.Commit();
  return true;
}

This one is not IMO :


public class MyProcessQueue
{
  public void ProcessQueue()
  {

    for(;;)
    {
       var p = Queue.Next();
       if (p==null)
         break;
       sProcessor.Process(p);
    }
  }
}

Since you can not infer the type from Queue, you should make the type explicit :


public class MyProcessQueue
{

  public void ProcessQueue()
  {

    for(;;)
    {
       Order o = Queue.Next();
       if (o==null)
         break;
       sProcessor.Process(o);
    }
  }
}


This would change if the MyProcessQueue would be a generic class :


public class MyProcessQueue<T> where T:ISomeInterface
{
  public void ProcessQueue()
  {

    for(;;)
    {
       var p = Queue.Next();
       if (p==null)
         break;
       sService.Process(p);
    }
  }
}



In this case, I think you have enough information available to know that the type should be about the generic class. Using more explicit names for the variables does not add a lot info for me; I do not find the following (exagerated) example more abvious than the previous one; in fact, it takes more time to get the intent here, because your mind needs to process more information (also note the comments, which do not provide any extra info to me) :


public class MyProcessQueue<T>
  where T:ISomeInterface

  // Process all jobs in the queue, until there is nothing left  
  public void ProcessAllISomeInterfacesInTheQueue()
  {
    // loop forever
    for(;;)
    {
       // get the next instance to process from the queue; 
       // if it returns null there are no more processes left on the queue 
       ISomeInterface TheNextISomeInterfaceInstanceToProcess = Queue.Next();

       if (TheNextISomeInterfaceInstanceToProcess==null)
       {
          //exit the infinite loop 
         break;
        }
       // process it 
       sServiceThatProcessesSomeInterfaceInstance
          .Process(TheNextISomeInterfaceInstanceToProcess);
       // go to the next one
    }
   // return 
  }
}

There is way too much info here which can all be easily derived from the code, and if you change the code and forget the comments, this might actually do the opposite: cause confusion.

In conclusion

While this is all about preference and highly dependent on you point of view and background, I do think that the approach I am personnaly using is one of the better ones. They offer all the amount of information that you could need with the minimum amount of code.

If you do have another opinion, do not hesitate to let me know...

 

Bookmark and Share

Tags: , , ,

CodeProject | Development | Howto | News

Screencast: Build an Asp.net MVC application quickly using MVCExtensions

by Tom 29. January 2010 20:16

Introduction

This is my first screencast for my MVCExtensions project, it shows you how to get started and build a simple tasklist.

PS: This is the direct link to the powerpoint used:
http://docs.google.com/present/view?id=dgt3mk3c_6fmhrd9c5

Some background info

This was my first screencast, and it took me about 7 attempts to finally get it to a point where it was more or less acceptable. For my sixth and seventh attempt I finally found some good screencap software : BBFlashback Express.

Anyway, this has been an interesting experience, and now enjoy mvcextensions !!!

More...

Tags: , , , , ,

CodeProject | Development | Howto | News

The advantage of using BDD over TDD

by Tom 26. January 2010 13:48

Introduction

After reading the latest post from @jeremydmiller I felt the urge to write a small article about the BDD part since there might be missing a vital part here about BDD...

More...

Tags: , , , , , , ,

CodeProject | Development | News

Build asp.net MVC applications FAST with MVCExtensions v0.4

by Tom 20. January 2010 19:28

Introduction

Today I finished v0.4 of my MVCExtensions library and I pushed the sourcecode to github.

I also included a very simple tasklist, in order to show you on how to get started using this library. You can also see (slightly outdated) example code in this blog post...

You can see a demo of the tasklist app running here. (Try entering a task without a name, or with a name that has more then 256 chars to see the custom strings in action).

You can download the full sourcecode here.

Update

I now made a screencast as well. it is available here.

More...

Tags: , , , , , , , , , , ,

CodeProject | Development | News

Teaser on my upcoming mvcextensions project release

by Tom 18. January 2010 15:51

Hi there,

I am going to give you a quick teaser on how to setup a full asp.net mvc application with database & all the rest using my soon-to-be-updated MVCExtensions library.

More...

Tags: , , , , , , , ,

CodeProject | Development | News

2009 retrospective: .Net technologies and lessons learned

by Tom 2. January 2010 03:02

my pride & joy

Introduction

 

In December 2008 I was doing my job as a freelance technical analyst for a big company. While it was a very interesting job in several ways, I felt that a burn-out was coming up. I had no idea whether this was due to the job, or due to my personal merits ( a newborn and a one-year old son, lots of tasks and chores on my to-do list for our house, a busy social life, ...) Instead of waiting for the man with the hammer, I decided to be proactive about it, so I decided to quit the job and reinvent myself during 2009.

It has been both an interesting, very challenging and enriching year for me, with both high peaks and low valleys.

I decided to write this blog post in order to evaluate myself, and I am hoping that other people might find some inspiration in this as well.

 

 

 

 

 

More...

Howto+why using a prototype & bdd for a project estimate + personal rant

by Tom 22. December 2009 13:57

Introduction

As you might or might not now, estimating the budget for a project can be very hard sometimes. In order to get started on a project we first need a real estimate of what the client will need, and the client should know what I am going to deliver to him/her.
What I personally learned from the past is that one can never be fine-grained enough, since there will always be mismatches somewhere.

We can however try to offer the client something that he/she can both understand and work with, next to a description of what everything should do (from a business point of view).

How can we do this, while investing as little work as possible ?

 

Unfortunately one can not correctly estimate projects without doing some work

As straightforward as this might seem, most people do not seem to be able to grasp this ( do not be ashamed; I have been guilty as well ).

In order to give a correct estimate, you have to INVEST a decent amount of TIME.

More...

Tags: , , , , ,

CodeProject | Development | Howto | News | Tom's blog

About me

Tom Janssens op LinkedIn

Tom Janssens op twitter

Core bvba RSS

My name is Tom Janssens and I am the owner of Core bvba, a software and consultancy company.
I am married to Liesbeth and have 2 sons named Quinten and Matisse.
ICT is both my job and passion.
Next to this my other hobby is actively playing music (mostly guitar).

More info about me and my company...

Recent Comments