Delphi Prism WPF Model View ViewModel Template

by John 7/2/2009 6:16:00 PM

 

I'm currently exploring WPF Futures. In particular I wanted to investigate the Model-View-ViewModel pattern, an example of which is provided as a project template from the download page.

Apparently this is the preferred pattern when developing WPF/Silverlight applications. It's worth googling "model view view model" to find interesting links regarding this.

Since its C# and I wanted to explore using Delphi Prism I decided to convert the provided template. I used the C# to Oxygene converter which can be found here. Considering the current download is marked as 0.2, it was a pretty painless job which required minimal code changes to the converted Oxygene code.

I have uploaded the source code to the template here . A Subversion client is required, I'm using TortoiseSVN.

Having downloaded the code you need to create a zip file containing the package. 

Assuming you had installed the templates into C:\develop\DelphiPrismTemplates, the 7Zip commandline from the C:\develop\DelphiPrismTemplates\WpfModelViewApplication\WpfModelViewApplication folder would be

7z.exe" a -r ..\WpfModelViewApplication.zip *

The resulting zip file then needs to be copied to the Oxygene Visual Studio project template directory, this is

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\Oxygene\Windows (WPF)\1033 

You then need to make Visual Studio aware of the new template, from the folder C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE, you can run the commandline devenv.exe /setup

Assuming everything worked ok, when you do a File New Project in Visual Studio you should have a WPF Model View Application project in the WPF section. This is shown in the screenshot below.

 

 

I used the template to follow a tutorial which can be found in the in the download from codeplex which can be found here. There a couple of documents included and they are informative.
 
The complete tutorial application can be found at CodeCentral at this location;
 
A screenshot of the running application is shown below
 
 
A word of warning, if you start an application using the template and run it unchanged, it doesn't display anything. Its worth looking at the supplied example, in particular app.xaml.pas to see what is being performed at startup. 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Delphi Prism | WPF

Implementing Dependency Injection using AOP

by John 5/21/2009 6:00:00 AM

Lately I've been making use of dependency injection. I've been using it in the development of applications to switch between test and production services without impacting the calling code. I have been doing this so that I might test specific parts of the code through unit testing without having to worry about setting up a database.

I'm using StructureMap in my example, which is intended to illustrate how one might go about performing dependency injection.  In the example below I've create an Invoice object. IRepository is an interface and TestRepository is a data access object which returns Invoices. Service is a class which makes uses Invoice Repositories. By using interfaces, I can at a later date with minimal change replace TestRepository with another class that performs data access against a database.

 

  Invoice=public class

  end;

  IRepository=public interface

    method FindAll:List<Invoice>;

  end;

  TestRepository=public class(IRepository)

  public

    method FindAll:List<Invoice>;

  end;

  Service=public class

  public

    constructor (repository:IRepository);

    method FindAllInvoices:List<Invoice>;

  end;

implementation

 

class method ConsoleApp.Main;

begin

  StructureMapConfiguration.BuildInstancesOf<IRepository>().TheDefaultIsConcreteType<TestRepository>();

  var service := ObjectFactory.GetInstance<Service>();

  var invoices:=service.FindAllInvoices;

end;

constructor Service(repository:IRepository);

begin

  self.repository:=repository;

end;

method Service.FindAllInvoices:List<Invoice>;

begin

result:=self.Repository.FindAll;

end; 

method Repository.FindAll:List<Invoice>;

begin

  var invoices:=new List<Invoice>;

  invoices.Add(new Invoice);

  invoices.Add(new Invoice);

  invoices.Add(new Invoice);

  result:=invoices;

end;

 

In the main method of ConsoleApp I'm doing a number of things.

1) Registering TestRepository as the type to return when an instance of IRepository is requested.

2) Requesting an instance of Service with dependencies injected.

3) Calling the FindAllInvoices on the service 

 

Its important to note that I could of done step (1) using a configuration file, which would better illustrate the power of dependency injection. I could switch between

a test and production version of the Repository with no changes to the code.

The downside I see of dependency injection is that your tied to creating instances of objects using factory method. Your also to a certain extent have a dependency on the  library your using, in this case StructureMap.

This being a continuation of my previous post, I'm going to demonstrate I think I quite an elegant solution to these two problems using AOP.

As in the previous post you can find the Aspect and an example at the Delphi Prism Aspects library.

If you open the solution, there are two projects to take a look at. Prism.StandardAspects.DependencyInjection which contains the PropertyDependencyInjector aspect and an example project showing how two use it which is called PropertyInjectorConsoleApplication.

Shown below is a sample of the code and its usage. In program.pas from the console application you can find the declaration of the InvoiceService. This time the aspect is intended for properties and I have highlighted the declaration below.

 

 InvoiceService=public class

  public

    [aspect:PropertyDependencyInjector]

    property ItemRepository:LineItemRepository;

    [aspect:PropertyDependencyInjector]

    property InvoiceRepository:InvoiceRepository;

    method GetAllInvoices:List<Invoice>;

  end;

 

Shown below is a code sample using the Service

 

    StructureMapConfiguration.BuildInstancesOf<IRepository<Invoice>>().TheDefaultIsConcreteType<InvoiceRepository>();

    StructureMapConfiguration.BuildInstancesOf<IRepository<LineItem>>().TheDefaultIsConcreteType<LineItemRepository>();

 

    var service:=new InvoiceService;

 

    if(assigned(service.InvoiceRepository))then

    begin

      var allInvoices:=service.InvoiceRepository.FindAll;

 

      if(allInvoices.Count=1)then

      begin

        Console.WriteLine(String.Format('Invoice Id{0}', allInvoices[0].Id));

      end

      else

      begin

        Console.WriteLine('No invoices ?');

      end;

    end

    else

    begin

      Console.WriteLine('No invoice repository');

    end;

In the above code example, the only way you would know the dependency injection is taking place are the two lines calling BuildInstancesOf

Otherwise your creating InvoiceService objects in the normal manner and calling the properties without even knowing anything is going on in the background.

 

Behind the scenes the aspect is modifying the getters and setters to call StructureMap. If you use Reflector to look at the final code  it should look like this

 

method InvoiceService.get_InvoiceRepository: InvoiceRepository;

begin

    if not self.@p_InvoiceRepository_injected then begin

        self.@p_InvoiceRepository_real := ObjectFactory.GetInstance<InvoiceRepository>;

        self.@p_InvoiceRepository_injected := true

    end;

    begin

        result := self.@p_InvoiceRepository_real;

        exit

    end

end;

Notice how the actual creation of property is delegated to StructureMap.

 

In conclusion, I think this is pretty cool. 

 

 

 

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

AOP | Delphi Prism | IOC

Powered by BlogEngine.NET 1.3.0.0
Theme by Mads Kristensen

About the author

Name of author John Moshakis
I'm a software developer living in Toronto..

E-mail me Send mail

Calendar

<<  July 2009  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Pages

    Recent comments

    Authors

    Tags

    Don't show

      Disclaimer

      The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

      © Copyright 2009

      Sign in