[C#]C# 4.0 動態繫結 (Dynamic Lookup)

Introduction

動態繫結是C# 4.0的特色之一,其功能在現階段與晚期繫結大同小異。有用過VB.NET晚期繫結的,相信都能很快速的上手。主要能讓程式在執行階段才指定型別,並進行動態叫用。

VB.NET在VB2005 (VB 7.0)開始支援晚期繫結 (Late-Binding)

Support

  • C# 4.0 or latter


動態繫結

動態繫結最大的功能就是能在執行階段才決定指定的型態,並在執行階段做型別檢查,且可動態叫用函示、運算、索引子、屬性、與欄位。不論你的物件是從COM、IronPython、HTML DOM、或是reflection所取得,動態繫結允許你採用一至的方法動態的去叫用它。

此外,使用動態繫結還有個好處,就是可以精簡程式碼。

像下面這樣的程式


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

在以往要達到動態的效果,我們可能會用反射來寫


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

或是寫成像下面這樣


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

但有了動態繫結我們可以更為精簡


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

在使用動態繫結時,IDE的IntelliSense功能會無法提示。不用太在意,直接輸入就可以了。若輸入錯誤或該成員不存在,則程式會在執行階段做告知的動作。

使用方式

在C# 4.0中要使用動態繫結我們可以使用dynamic關鍵字。讓我們直接來看New Features in C# 4.0文件中的程式碼片段。


dynamic d = GetDynamicObject(…);
d.M(7); // calling methods
d.f = d.P; // getting and settings fields and properties
d[“one”] = d[“two”]; // getting and setting thorugh indexers
int i = d + 3; // calling operators
string s = d(5,7); // invoking as a delegate

相信多數人光看這個程式碼片段還是很模糊,但起碼能從中了解它能動態叫用方法、欄位與運算子、索引子、委派。

接著我們再看一範例應該就會清楚些


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
dynamic[] ds = new dynamic[2];
ds[0] = new System.Windows.Forms.TextBox(){Name=”TextBox”};
ds[1] = new Person() { Name = “Larry” };
foreach (dynamic d in ds)
{
Console.WriteLine(d.Name);
}
}
}
class Person
{
public string Name { get; set; }
}
}

由於不用把型態從Object轉回匿名型別,因此動態繫結也可以用在匿名型別上,真的方便許多,看來以後若要偷懶直接傳遞匿名型別也可以了(不建議也不鼓勵濫用)。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication19
{
class Program
{
static void Main(string[] args)
{
dynamic d = new { Name = “Larry” };
Console.WriteLine(d.Name);

        d = GetLarry();
        Console.WriteLine(d.Name);
    }

    static dynamic GetLarry()
    {
        return new { Name = "Larry" };
    }
}

}

就算回傳值改為Object也可以使用


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication19
{
class Program
{
static void Main(string[] args)
{
dynamic d = new { Name = “Larry” };
Console.WriteLine(d.Name);

        d = GetLarry();
        Console.WriteLine(d.Name);
    }

    static Object GetLarry()
    {
        return new { Name = "Larry" };
    }
}

}

Link