Saturday, July 19, 2008

Velocity: Microsoft's Distributed In-Memory Cache

Distributed in-memory caches have been rather popular over the last few years in everything from mainstream Java applications to the fringe languages like Erlang. Continuing its rather frantic efforts to catch up with technologies predominately found in the open source world, Microsoft has introduced its own distributed cache.

Velocity is a distributed cache designed specifically for the .NET platform. Many of the features will be recognizable to those familiar with other distributed in-memory caches. It is currently available as a community tech preview.

There are two types of clients for Velocity. Simple clients only know about a single cache server. If the requested object is not available on that cache server, the cache server will fetch it from the appropriate server. Routing clients are much more involved. They always know where a particular object lives so they can query that cache server directly. The performance impact of sending all of the cache location data to a routing client hasn't been discussed. In addition to the cache servers, both types of clients support a local cache option. This still requires checking the server for stale data, but should reduce network traffic when dealing with large cache objects.

For concurrency two options exist. With optimistic concurrency, the first update wins and any further updates to the now stale object will fail. With pessimistic locking, a lock handle is returned. Until unlocked, or the timeout expires, all attempts to gain a lock will fail. Failure to obtain a lock is a non-blocking operation.

Objects can be removed from the cache explicitly, via a expiration date, or whenever memory pressure is exceeded. This last method, known as eviction, uses a least recently used algorithm.

In addition to a key, objects may have a collection of tags associated with them. There are methods to retrieve one or all objects that match a list of tags.

http://www.infoq.com/news/2008/06/Velocity;jsessionid=1A186B573B980B4638C65CDEDF143B60

Wednesday, July 16, 2008

Cách tạo shortcut trên Desktop cho ứng dụng được triển khai bằng ClickOnce

Khi thực hiện triển khai ứng dụng bằng ClickOnce, nó chỉ tạo ra shortcut trên All Programs menu với đường dẫn là <CompanyName>/<ProductName>, trong đó <CompanyName> và <ProductName> đã được đăng ký trong Assembly của ứng dụng. Đoạn code sau đây sẽ thực hiện việc tự động copy shortcut từ trên menu Programs vào Desktop. Bạn nên đưa phương thức này vào Form Main của ứng dụng.

//    Khi đưa vào chương trình nên chú ý kiểm tra xem bạn có đang debug trên Visual Studio hay không?
//    #if (!debug)
//        CheckForShortcut();
//    #endif
 
//Namespace Referrence
// using System.Deployment.Application;
// using System.Reflection;
 
void CheckForShortcut()
{
    ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
 
    if (ad.IsFirstRun)
    {
        Assembly code = Assembly.GetExecutingAssembly();
 
        string company = string.Empty;
        string productName = string.Empty;
 
        if (Attribute.IsDefined(code, typeof(AssemblyCompanyAttribute)))
        {
            AssemblyCompanyAttribute ascompany = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(
                code, typeof(AssemblyCompanyAttribute));
 
            company = ascompany.Company;
        }
 
        if (Attribute.IsDefined(code, typeof(AssemblyProductAttribute)))
        {
 
            AssemblyProductAttribute asProductName = (AssemblyProductAttribute)Attribute.GetCustomAttribute(
                code, typeof(AssemblyProductAttribute));
 
            productName = asProductName.Product;
        }
 
        if (company != string.Empty && productName != string.Empty)
        {
 
            string desktopPath = string.Empty;
 
            desktopPath = string.Concat(Environment.GetFolderPath(
                Environment.SpecialFolder.Desktop), "\\", productName, ".appref-ms");
 
            string shortcutName = string.Empty;
 
            shortcutName = string.Concat(
                Environment.GetFolderPath(Environment.SpecialFolder.Programs),
                "\\", company, "\\", productName, ".appref-ms");
 
            System.IO.File.Copy(shortcutName, desktopPath, true);
        }
    }
}

Tuesday, July 8, 2008

Tài liệu tham khảo nhanh dành cho .NET Developer

    Cách thiết lập focus cho một control khác sau khi sử lý sự kiện AfterSelect của TreeView

    TreeView control có thể gây cho bạn khó khăn trong trường hợp này, nó cập nhật lại Node được lựa chọn và thực hiện focus trở lại Node này sau khi xử lý sự kiện. Cách thực hiện cho trường hợp này là làm trễ việc thực thi đoạn code của bạn cho đến khi hoàn thành việc xử lý sự kiện trên control TreeView. Dưới đây là sample cho việc xử lý trường hợp này:

    private delegate void FocusAfterSelect(TreeNode node);
     
    private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) 
    {
        this.BeginInvoke(new FocusAfterSelect(HandleAfterSelect), e.Node);
    }
     
    private void HandleAfterSelect(TreeNode node) 
    {
        textBox1.Text = node.Text;
        textBox1.Focus();
    }

    Monday, July 7, 2008

    Truy cập các phương thức private sử dụng Reflection trong .NET.

    Để truy cập vào các phương thức hoặc thuộc tính private của một lớp, ta sẽ sử dụng gói Reflection được xây dựng bên trong .NET Framework. Để minh họa cho khả năng của của Reflection trong .NET Framework, tôi xin đưa ra một ví dụ bên dưới:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;
     
    namespace ReflectionSamples
    {
        public class ReflectionSample
        {
            private void Method1()
            {
                Console.WriteLine("Method 1 called");
            }
            
            private int Method2(int x, int y)
            {
                Console.WriteLine("Method 2 called {0}, {1}", x, y);
                return x*y;
            }
            
            internal string RedAlert
            {
                get
                {
                    Console.WriteLine("Red Alert");
                    return "Red Alert";
                }
            }
        }
        
        internal class Program
        {
            private static void Main(string[] args)
            {
                //Tạo instance của lớp mà ta sẽ thực hiện truy cập các hàm private
                MyClass instance = new MyClass();
                
                //Get Type of class
                Type t = typeof (MyClass);
                
                //Lấy thông tin của phương thức Method1
                MethodInfo method1 = t.GetMethod("Method1",
                    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod);
     
                //Gọi phương thức trên đối tượng được tham chiếu bằng instance và truyền tham số
                method1.Invoke(instance, null);
                
                //Truy cập thông tin của Properties
                PropertyInfo property = t.GetProperty("RedAlert", 
                    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty);
                
                //Gọi Properties tương ứng và truyền tham số
                string str = (string)property.GetValue(instance, null);
                
                //Truy cập thông tin của phương thức Method2
                MethodInfo method2 = t.GetMethod("Method2", 
                    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod);
     
                //Gọi phương thức và truyền 2 tham số (các tham số được truyền thông qua danh sách đối tượng
                object o = method2.Invoke(instance, new object[] {2, 3});
                
                //Với trường hợp phương thức có giá trị trả lại
                if (o != null)
                {
                    Console.WriteLine("Method 2 returned: " + o.ToString());
                }
                
                Console.ReadKey();
            }
        }
    }