Thứ Năm, 13 tháng 5, 2010

Lập trình động trong .NET 4.0 và WPF 4.0

Năm 2010 là thời điểm mà Microsoft sẽ công bố hàng loạt các sản phẩm công nghệ mới. Trong đó phải kết đến như Microsoft Office 2010, SharePoint 2010 và đặc biệt là bộ công cụ phát triển cho các lập trình viên, Visual Studio 2010. Đi kèm với Visual Studio 2010 là nền tảng phát triển mới .NET 4.0 mạnh mẽ. NET 4.0 hứa hẹn sẽ mở ra một cuộc cách mạng trong phát triển ứng dựng dựa trên nền tảng Microsoft. Nó thúc đẩy quá trình phát triển phần mềm, trở nên linh hoạt hơn và nhanh chóng hơn.

Lập trình động (Dynamic programming)

Có thể nói nét chủ đạo trong .NET 4.0 đó là lập trình động (dynamic programming). Các đối tượng (object) ngày nay trở nên động (dynamic) theo ý nghĩa là cấu trúc và hành vi của nó không bị bó buộc bởi kiểu dữ liệu tĩnh (static) như trước đó, đồng thời trình biên dịch không cần biết kiểu dữ liệu của đối tượng trong quá trình biên dịch chương trình. Điều này sẽ rất có ích khi chương trình cần phải tương tác với các đối tượng từ các ngôn ngữ lập trình động giống như Python hoặc Ruby, hay là làm việc với các đối tượng mà có sự thay đổi về mặt cấu trúc như HTML hoặc DOM. Qua đó chúng ta có thể sử dụng nhiều ngôn ngữ khác nhau trên cùng một ứng dụng. Các đoạn mã của C#, VB.NET, IronPython,Javascripts… có thể hòa trộn với nhau để tạo ra một chương trình hoàn chỉnh.

Với dynamic trong .NET 4.0, khi lập nhận được một đối tượng, chúng ta không cần phải quan tâm đối tượng đó đến từ COM, IronPython hay HTML DOM hoặc Reflection. Chúng ta có thể sẵn sàng áp dụng các phép toán cho nó và để cho môi trường thực thi quyết định phép toán nào sẽ áp dụng cho đối tượng nào.

Lấy ví dụ:

Gọi phương thức từ lớp C#

Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);


Gọi thông qua Reflection:



object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add",
    BindingFlags.InvokeMethod, null,
    new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

Gọi thông qua DOM:



ScriptObject calc = GetCalculator();
object res = calc.Invoke("Add", 10, 20);
int sum = Convert.ToInt32(res);

Với dynamic C# 4: Chúng ta không cần quan tâm đối tượng trả về từ phương phương thức GetCalculator() thuộc lớp C#, Reflection hay DOM. Trong khi chúng ta vẫn có thể tiến hành gọi phương thức Add của nó. Rõ ràng doạn mã này ngắn gọn và dễ hiểu hơn rất nhiều trước đó.



dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

System.Dynamic.DynamicObject


. NET 4.0 giới thiệu một lớp mới gọi là DynamicObject cho phép định nghĩa các hành vi có thể được thực thi trong quá trình chạy. Đây là một đặc trưng rất mới trong .NET 4.0. Chúng ta biết rằng các đối tượng trong .NET 3.5 và trước đó đều phải xác định cấu trúc và các hành vi trong quá trình biên dịch. Với DynamicObject cho phép các lập trình viên xây dựng các đối tượng một cách linh hoạt hơn. Việc lấy giữ liệu hay xác định hành vi cho đối tượng có thể được quyết định và thực thi trong quá runtime. Lập trình viên sẽ viết mã để điều khiển quá trình lấy và thao tác giữ liệu cho đối tượng. Điều này sẽ rất có ích khi chúng ta làm việc các đối tượng có sự thay đổi về mặt cấu trúc như XML hay ADO object.


Lấy ví dụ: Bài toán đọc một đối tượng XML


Trước hết chúng ta khai báo một lớp kế thừa từ DynamicObject



public class EasierXML : DynamicObject
    {
        private XDocument _xml = new XDocument();
        public EasierXML(string Xml)
        {
            this._xml = XDocument.Parse(Xml);
        }
        public override bool TryGetMember(GetMemberBinder binder,
            out object result)
        {
            string nodeName = binder.Name;
            result = _xml.Element("test").Element(nodeName).Value;
            return true;
        }
    }  



Chúng ta sử dụng đối tượng này để đọc cấu trúc XML như sau:



dynamic easierXML =
                new EasierXML(@"<test><node1>Alpha</node1><node2>Beta</node2></test>");
Console.WriteLine(easierXML.node1);
Console.WriteLine(easierXML.node2);  

Trong ví dụ này, phương thức TryGetMember() được gọi đến cho node1, node2, do đó cho phép
truy vấn tài liệu XML và trả lại các nút riêng lẻ. Trong trường hợp cấu trúc XML có sự thay đổi, có một số node nào đó được thêm, chúng ta chỉ việc gọi đến easierXML.node3, easierXML.node4,.. mà không cần phải thay đổi đến lớp EasierXML


Một ví dụ khác, sử dụng DynamicObject còn giúp chương trình giảm thiểu được các lỗi phát sinh trong quá trình ép kiểu giữ liệu khi chúng ta làm việc với các đối tượng ADO.


Theo cách lập trình thông thường: chúng ta phải tiến hành ép kiểu mỗi khi đọc giá trị từ database



com.CommandText = "SELECT * FROM Employees";
                using (IDataReader reader = com.ExecuteReader())
                {                    
                    while (reader.Read())
                    {
                        int id = Int32.Parse(reader["EmployeeID"].ToString());
                        string firstName = reader["FirstName"].ToString();
                        DateTime dob = DateTime.Parse(reader["BirthDate"].ToString());
                    }
                }


Sử dụng dynamic: kiểu dữ liệu được tự động xác định trong quá trình thực thi



com.CommandText = "SELECT * FROM Employees";
                using (IDataReader reader = com.ExecuteReader())
                {
                    dynamic dr = new DynamicReader(reader);
                    while (reader.Read())
                    {                        
                        int id = dr.EmployeeID;
                        string firstName = dr.FirstName;
                        DateTime dob = dr.BirthDate;
                    }
                }

Ứng dụng dynamic cho WPF 4 trong quá trình gắn kết giữ liệu động (dynamic binding)


Trên đây là nét đặc trưng trong nền tảng ngôn ngữ .NET 4.0 đó là dynamic programming. Vậy chúng ta có thể ứng dụng nó vào các bài toán thực tế như thế nào? Lấy một ví dụ cho một ứng dụng desktop client sử dụng WPF. Như chúng ta biết rằng WPF tách biệt phần hiển thị của ứng dụng với các đoạn mã logic. Điều đó giúp cho các lập trình viên và các nhà thiết kế có thể làm việc độc lập mà vẫn không ảnh hưởng tới quá trình phát triển của ứng dụng. Các ứng dụng ngày nay thường được phát triển thông qua kiến trúc nhiều tầng. Một kiến trúc căn bản bao gồm tầng thể hiện, tầng logic nghiệp vụ và tầng thao tác dữ liệu. Thông thường, tầng thể hiện sẽ phát sinh nhiều yêu cầu thay đổi nhất từ phía khách hàng, trong khi tầng thao tác giữ liệu phải đảm bảo tính ổn định về mặt kiến trúc. Dó đó một kiến trúc tốt cần đảm bảo những yêu cầu thay đổi từ phía khach hàng không làm ảnh hưởng quá nhiều đến thiết kệ hiện có của ứng dụng, đặc biệt là các thiết kế liên quan đến thao tác giữ liệu.


Xét một ví dụ sau: Quản lý thông tin cá nhân


Giữ liệu được lưu trong 1 file XML có cấu trúc:



<?xml version="1.0" encoding="utf-8" ?>
<People>
  <Person>
    <FirstName>Quang</FirstName>
    <LastName>Nguyễn Bá</LastName>
  </Person>
  <Person>
    <FirstName>Cường</FirstName>
    <LastName>Trịnh Minh</LastName>
</Person>

Các tiếp cận trước đây (chưa có dynamic)


Thực thể (Business Entity)

Khai báo một lớp Person



public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

Thao tác giữ liệu (Data access)

Lấy giữ liệu từ nguồn (trong ví dụ này sử dụng XML là nguồn lưu trữ giữ liệu, tương tự chúng ta có thể thay thế XML bằng CSDL có cấu trúc như SQL Server, Oracle)



public IEnumerable<Person> GetData()
        {
            XDocument oDoc = XDocument.Load("People.xml");
            var myData = from info in oDoc.Descendants("Person")
                         select new Person
                         {
                            FirstName = info.Element("FirstName").Value,
                            LastName = info.Element("LastName").Value,                             
                         };
            return myData.ToList<Person>();
        }

Hiển thị (Presentation)

Gắn kết giữ liệu và hiển thị lên controls:



<DataGrid Name="myDataGrid" VerticalAlignment="Top" ItemsSource="{Binding}" AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="firstNameColumn" 
              Binding="{Binding Path=FirstName}" 
              Header="First Name" Width="SizeToHeader" />
            <DataGridTextColumn x:Name="lastNameColumn" 
              Binding="{Binding Path=LastName}" 
              Header="Last Name" Width="SizeToHeader" />            
        </DataGrid.Columns>
</DataGrid>   

Điều gì sẽ xảy ra nếu khách hàng yêu cầu quản lý thêm thông tin về tuổi (Age) và giới tính (isMale). Rõ ràng với cách thiết kế trên chúng ta phải thay đổi tất cả các tầng trong kiến trúc của ứng dụng. Điều đó làm tăng chi phí cho việc nâng cấp ứng dụng, điều mà cả khách hang và nhà phát triển đều không mong muốn.


Vậy làm sao để giải quyết vấn đề trên?


Sử dụng dynamic binding (gắn kết động)


Thực thể (Business Entity)

Triển khai DynamicObject. Lớp này có thể sử dụng cho tất cả các nguồn giữ liệu là XML mà không phân biệt cấu trúc của nó. Nhiệm vụ của nó là lấy ra một cách chính xác giá trị trong các thẻ XML



class DynamicXML : DynamicObject
    {
        XElement _element;
        public ReadXML(XElement e) { _element = e; }
        public override bool TryGetMember(GetMemberBinder binder,
        out object result)
        {
            //Triển khai phương thức lấy giá trị của đối tượng           
        }
    }

Thao tác giữ liệu (Data access)

Lấy giữ liệu từ nguồn và trả về đối tượng dynamic



dynamic GetPersonData()
        {
            var root = XElement.Load("People.xml");
            dynamic xml = new DynamicXML(root);           
            return xml.Person;
        }

Hiển thị (Presentation)

Gắn kết giữ liệu và hiển thị lên controls



<DataGrid Name="myDataGrid" VerticalAlignment="Top" ItemsSource="{Binding}" AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="firstNameColumn" 
              Binding="{Binding Path=FirstName}" 
              Header="First Name" Width="SizeToHeader" />
            <DataGridTextColumn x:Name="lastNameColumn" 
              Binding="{Binding Path=LastName}" 
              Header="Last Name" Width="SizeToHeader" />            
        </DataGrid.Columns>
</DataGrid>   

Trong trường hợp khách hàng yêu cầu quản lý thêm thông tin về tuổi (Age) và giới tính (isMale). Điều duy nhất mà chúng ta phải làm đó là yêu cầu người thiết kế ứng dụng thêm đoạn mã sau vào phần hiển thị, trong khi không phải thay đổi hay biên dịch lại các tầng khác của ứng dụng. Qua đó đảm bảo tính vững chắc của kiến trúc chương trình cũng như giảm thiểu chi phí cho nâng cấp ứng dụng rất nhiều mỗi khi có yêu cầu thay đổi từ phía khách hàng.



<DataGridTextColumn x:Name="ageColumn" Binding="{Binding Path=Age}" Header="Age" Width="SizeToHeader" />
<DataGridTextColumn x:Name="isMaleColumn" Binding="{Binding Path=IsMale}" Header="Is Male" Width="SizeToHeader" />

Rõ ràng, với cách tiếp cận sử dụng dynamic, chúng ta thấy rằng số lượng mã cần thiết để viết và thay đổi cho một chức năng của chương trình ít hơn rất nhiều cách trước đó.


Kết luận


Trong tháng 4/2001 Microsoft sẽ chính thức ra mắt bộ công cụ Visual Studio 2010 và nền tảng phát triển .NET 4.0. Sự kiện này đã và đang mở ra hướng mới trong ngành công nghiệp phần mềm, với sự linh hoạt và khả năng xây dựng ứng dụng một cách nhanh chóng mà vẫn đáp ứng được những yêu cầu ngày các khắt khe của người dùng.


basquang@hotmail.com


source code

SharePoint 2010: ReportViewer with Access Services

Error:

Session state has been disabled for ASP.NET. 
The Report Viewer control requires that session state be enabled in local mode


When I try to view ReportViewer that published from Access Web Database to SharePoint site.


Solution:


- enable-SPSessionStateService


- IISRESET



Thanks, that did the trick. In fact, from the SharePoint powershell prompt I can just enter one command:
 
enable-SPSessionStateService
 
It then prompts for a session database to create. I just used dbSession (but foo or any name should work).
 
It all works just fine now. Thanks a bunch.
 
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
kallal@msn.com

Thứ Tư, 12 tháng 5, 2010

SharePoint 2010: PerformancePoint Services Dashboard Designer

Error:

The data source no longer exists or you do not have permissions to view it.

Additional details have been logged for your administrator.


Solutions:


Hi,
Please install the WCF hot Fix for Windows Server 2008 R2 prior to this step.  I believe it should be public soon.
Can you please verify the following see it helps? 
1. Central Administration | Application Management | Manage Service Application | Double click Secure Store Application | Generate New Key
2. Central Administration | Application Management | Manage Service Application | PerformancePoint Service Application | Manage | Update the PerformancePoint Unattended Service Account – First option   
This step needs to be successful, if there is a failure please delete the PerformancePoint Service Application and recreate it.
3. Central Administration | Application Management | Manage Service Application | PerformancePoint Service Application | Administrator | Add the Unattended Service Account and Mark Full Control.
Thank you,
Sundar – MSFT

MSDN

Thứ Sáu, 2 tháng 4, 2010

MoneyManagement: Phần mềm quản lý thu chi cá nhân trên PocketPC và PC

Phần mềm này tôi viết ra để giúp vợ tôi dễ dàng hơn trong việc quản lý chi tiêu trong gia đình. Bằng cách sử dụng điện thoại di động là một chiếc smartphone O2 mini S, người dùng có thể dễ dàng quản lý thông tin thu/chi theo thời gian, qua đó xác định được kế hoạch cho việc chi tiêu sắp tới.

Các chức năng chính bao gồm:

1. Nhập thông tin Thu/Chi

A21319952F68E79E_704_0[1]

2. Xem báo cáo: Cho phép người dùng lọc thông tin báo cáo theo ngày tháng và loại thay đổi Thu/Chi

A21319952F68E79E_704_1[1]

3. Thao tác trên máy tính: Chức năng này cho phép đồng bộ dữ liệu giữa điện thoại và máy tính. Cho phép người dùng có thể thao tác dữ liệu trên máy tính bằng công cụ Microsoft Office InfoPath

 

Phần mềm tương thích với Windows Mobile 5, 6, 7. Các bạn download tại địa chỉ sau: http://cid-a21319952f68e79e.skydrive.live.com/self.aspx/.Public/MoneyManagement/MoneyManagement.rar

Đây là một phần mềm hết sức đơn giản. Các bạn có thể tự tạo những phần mềm hữu ích cho mình trên nền Windows Mobile cũng như Windows sử dụng công cụ Visual Studio. Với ứng dụng cho Windows Phone 7, các bạn có thể xem các bài hướng dẫn rất hay tại địa chỉ

http://channel9.msdn.com/learn/courses/WP7TrainingKit/

Comments

Thinh Nguyen - 4/6/2010 10:02:25 AM
Có làm 1 bản trên iPhone ko mày :D
Quang Nguyen Ba - 4/6/2010 10:24:15 AM
Trả tiền thì làm ngay :D
thangbomvn - 4/6/2010 2:14:05 PM
Tiếc ghê, em vừa mua iphone. Đang cân nhắc xem có nên dùng HTC Snap ko :)
Tien Do - 4/14/2010 8:45:58 PM
Sao lại tiếc, có thằng Quang mới phải tiếc vì thay vì viết cho iPhone mốt mới thời đại thì lại viết cho cái O2miniS cũ rích hê hê :D

@iPhone users: Trên App Store đầy app. kiểu này, có cái CashTrailz chẳng hạn, hơi bị hay :)