May 2011 - Posts

Dependency Injection dengan Unity Application Block


Unity Application Block adalah salah satu Dependency Injection (DI) framework yang dapat digunakan dalam dunia pemrograman .NET yang ditawarkan oleh Microsoft Patterns & Practices. Sebenarnya Unity sudah ada sejak Enterprise Library 4.x dan masih terus dikembangkan sampai Enterprise Library 5.0.

Ide awal dari DI adalah menghilangkan “dependency” antara object dengan sebuah class. Misalkan code C# berikut ini:

IDbConnection connection = new SqlConnection();

dari code di atas dapat dikatakan bahwa objek connection mempunyai “dependency” dengan SqlConnection. Dalam contoh ini, code di atas ingin mengatakan bahwa aplikasi ingin mengakses database SQL Server melalui objek connection.

Apabila suatu saat kita ingin mengubah connection ke database lain, misalnya ke database Microsoft Access, tentunya kita harus mengubah code di atas menjadi:

IDbConnection connection = new OleDbConnection();

dan kita harus mengkompilasi ulang kembali code tersebut….whew!

Salah satu blog yang menjelaskan istilah Dependency Injection dengan bahasa yang sangat dimengerti adalah di blog ini.

Untuk menggunakan Unity, tambahkan reference ke tiga assembly berikut:

  1. Microsoft.Practices.Unity
  2. Microsoft.Practices.Unity.Configuration
  3. System.Configuration

Assembly ketiga diperlukan jika kita menggunakan assembly yang kedua, yaitu menggunakan Unity dengan konfigurasi file.

Misalkan kita mempunyai interface IDocument dengan definisi sebagai berikut:

public interface IDocument
{
   string Text { get; set; }
   void Save();
}

Dan class WordDocument yang mengimplementasikan IDocument:

    public class WordDocument : IDocument
    {
        private string text;
        public string FileName { get; set; }  // auto property

        public WordDocument(string initialText) // parameterized constructor
        {
            this.text = initialText;
        }

        public string Text
        {
            get
            {
                return text;
            }
            set
            {
                this.text = value;
            }
        }

        public void Save() // implemented method
        {
            Console.WriteLine("Saving word document");
        }        
    }

File konfigurasi untuk unity pada app.config adalah sebagai berikut:

<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>

<unity xmlns="
http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="IDocument"
           type="LearnUnity.IDocument, LearnUnity" />
    <container> 
      <register type="IDocument" 
               
mapTo="LearnUnity.WordDocument, LearnUnity">
        <constructor>
          <param name="initialText"
               
value="this is the initial text, we can change this anytime" />
        </constructor>
      </register>

    </container>
</unity>

Konfigurasi Unity di atas ingin mengatakan bahwa ketika objek yang mengimplement IDocument diresolve, container harus meng-inject parameter di constructor dengan value tertentu.

Langkah pertama adalah membuat Unity container:

IUnityContainer container = new UnityContainer();
container.LoadConfiguration();

Baris kedua di atas menginstruksikan Unity untuk membaca file konfigurasi di app.config

Lalu kita dapat meresolve objek berdasarkan konfigurasi yang sudah kita buat:

IDocument doc = container.Resolve<IDocument>();
Console.WriteLine(doc.Text);

Jika code di atas dijalankan, terlihat bahwa value yang kita sebutkan di konfigurasi sudah di-inject melalui constructor saat objek doc dicreate melalui Unity container.

Kesimpulan:
Dengan Dependency Injection, kita dapat menurunkan coupling antara objek dengan class, karena kita tidak langsung membuat instance dari sebuah class, melainkan membuat objek dari interface yang mana interface ini diimplementasikan oleh class tersebut. Dependency Injection ini berguna ketika kita ingin membuat unit test, dengan membuat mock object, yaitu sebuah objek yang semua behaviornya menyerupai behavior konkritnya. Contoh code dapat diunduh di attachment dari post ini.

Share this post: | | | |
Posted by paulus with no comments
Filed under: ,

Creating Office Document using UNO

One of my clients want to “migrate” their software infrastructure from Microsoft Office to OpenOffice. But, the main problem for them is they have used Office library in their applications. Yes, they have used “Excel.Application” and “Word.Application” ActiveX library to instantiate office documents. The term “documents” here means Word document and Excel spreadsheet.

The first solution across my mind is we have to “migrate” their ActiveX implementation to other library that can create Microsoft Office documents, for example: NPOI. But wait a minute, their "document”-generator is scripted in JavaScript! Geez……they can compose a document using JavaScript, it’s generated on-the-fly at client side, definitely not at server side!

After googling and googling, I found UNO. In simple term, UNO is a component object model for OpenOffice. UNO can be used in various programming language, such as Java, Python, C#, and of course, JavaScript. UNO objects can be instantiated using JavaScript through COM Automation. In JavaScript, we can use new ActiveXObject(name of UNO class) to instantiate UNO objects.

For example:

var svcMgr = new ActiveXObject("com.sun.star.ServiceManager");

Code above means, we create an object svcMgr as an instantiate of com.sun.star.ServiceManager class.

We can read a complete reference of UNO in the OpenOffice SDK, which can be downloaded from this link. In the SDK, we can also read a complete documentation of UNO (or we can read it at  this site), including code samples.

In this post, I show you how to create a simple OpenOffice Calc spreadsheet, and save it as example.xls (which we can open it using Microsoft Excel later). But, before we start to code, we have to download the OpenOffice (I used OpenOffice 3.3) and the OpenOffice SDK.

Now, take a look at this JavaScript code:

function generateSpreadsheet() { 
var svcMgr = new ActiveXObject("com.sun.star.ServiceManager");    
var coreRef = svcMgr.createInstance("com.sun.star.reflection.CoreReflection");
var desktop = svcMgr.createInstance("com.sun.star.frame.Desktop");
var args = [];
var doc = desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, args);

var sheets = doc.Sheets
var sheet = sheets.getByIndex(0);

// fill data
sheet.getCellRangeByName("B2").String="ItemCode";
sheet.getCellRangeByName("C2").String="Qty";
sheet.getCellRangeByName("D2").String="Amount";
sheet.getCellRangeByName("E2").String="Total";

sheet.getCellRangeByName("B3").String="A01";
sheet.getCellRangeByName("C3").Value=2 ;
sheet.getCellRangeByName("D3").Value=100000;
sheet.getCellRangeByName("E3").Formula="=C3*D3";

sheet.getCellRangeByName("B4").String="A02";
sheet.getCellRangeByName("C4").Value=5 ;
sheet.getCellRangeByName("D4").Value=120000;
sheet.getCellRangeByName("E4").Formula="=C4*D4";

sheet.getCellRangeByName("B5").String="A01";
sheet.getCellRangeByName("C5").Value=3;
sheet.getCellRangeByName("D5").Value=200000;
sheet.getCellRangeByName("E5").Formula="=C5*D5";
    
sheet.getCellRangeByName("E6").Formula="=SUM(D3:D5)";
sheet.getCellRangeByName("E6").setPropertyValue("CharWeight", 150);    
sheet.getCellRangeByName("E6").setPropertyValue("CharColor", 16711680);
sheet.getCellRangeByName("E6").HoriJustify = 2;

sheet.getCellRangeByName("B6:D6").merge(true);
var url = "file:///C:/example.xls";
var arg = new Array();
arg[0] = MakePropertyValue(svcMgr, "FilterName", "MS Excel 97");
try
{
    doc.storeToURL(url, arg);
}
catch(e)
{
    alert(e.toString());
}
doc.close(true);
doc = null;
coreRef = null;
svcMgr = null;
}

You can copy-paste code above to Notepad, and save it as a JavaScript file, such as createcalc.js

Then create a new HTML document like this one:

<html>
<head>
    <script src="createcalc.js" type="text/javascript" language="javascript"></script>
</head> <body> <form> <input type="button" value="print" onclick="generateSpreadsheet();" /> </form> </body> </html>

Save it as CreateCalc.htm, then open it using Internet Explorer (we can use IE 6 or a newest one). The result of the script is:

image

The hardest part to write the script above is that we don’t know the constant value of a constant parameter. Take a look at this line:

sheet.getCellRangeByName("E6").setPropertyValue("CharWeight", 150); 

What is 150? Actually it is a bold constant value, in UNO, it is declared in class com.sun.star.awt.FontWeight, and the class consists some constants about font weight. Let’s take a look at the SDK folder: C:\Program Files\OpenOffice.org 3\Basis\sdk\docs\common\ref\com\sun\star\awt\FontWeight.html

To get the real constant value, take a look at the IDL folder: C:\Program Files\OpenOffice.org 3\Basis\sdk\idl\com\sun\star\awt\FontWeight.idl, it is clearly written that for the “bold” font style, the constant value must be set to 150.

Since I have to start this project immediately, if you have any experience developing office documents using UNO, please drop me an email or just comment this post. Thank you.

Share this post: | | | |
Posted by paulus with no comments