C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的應用(下)

來源:互聯網
上載者:User

接上文:C# Dynamic關鍵字之:ExpandoObject,DynamicObject,DynamicMetaOb的應用(上)

為什麼TryXXX方法沒有被調用??

將DynamicProduct 中的name修飾符改為private:

private string name;

可以在TrySetMember方法中設定斷點,再次運行:

為什麼存取修飾詞是Public不調用TrySetMember,是Private 就調用了呢??

難道是因為private拋出了異常嗎??

再次看看Msdn對此的TrySetMember方法的解釋:

Msdn備忘

…………….動態語言運行庫 (DLR) 將首先使用語言聯編程式在類中尋找屬性的靜態定義。 如果沒有此類屬性,DLR 調用 TrySetMember 方法。

問題的原因是這樣的:首先DLR 使用語言聯編程式在類中尋找name的靜態定義,

因為name是public,所以尋找到了,然後返回,不會去調用TrySetMember方法了,

但是如果name是private,那麼聯編程式在類中沒找到name的靜態定義,於是DLR嘗試調用TrySetMember方法。

修改TrySetMember方法如下:

複製代碼 代碼如下:public override bool TrySetMember(SetMemberBinder binder, object value)
{
Console.WriteLine("TrySetMember被調用了,Name:{0}", binder.Name);
bool result = base.TrySetMember(binder, value);

return true;
}

運行,可以發現不會拋出異常了:

總結:首先DLR會嘗試尋找屬性的靜態定義,如果沒有找到則會調用相應的TryXXX 方法,如果TryXXX方法返回false,代表TryXXX方法運行失敗,DLR隨後會拋出異常。

為了驗證是不是這樣,將DynamicProduct中屬性的靜態定義全部注釋掉,並且TryXXX方法全部返回True。完整的代碼如下:

複製代碼 代碼如下:class DynamicProduct : DynamicObject
{
#region dynamicProduct 的一些屬性的靜態定義

//private string name;
//public int Id { get; set; }

//public void ShowProduct()
//{
// Console.WriteLine("Id={0} ,Name={1}", Id, name);
//}

#endregion

#region Override DynamicObject 的方法

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
Console.WriteLine("TryGetMember被調用了,Name:{0}", binder.Name);
bool tryResult = base.TryGetMember(binder, out result);

return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
Console.WriteLine("TrySetMember被調用了,Name:{0}", binder.Name);
bool tryResult = base.TrySetMember(binder, value);

return true;
}

public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
Console.WriteLine("TryInvoke被調用了");
bool tryResult = base.TryInvoke(binder, args, out result);

return true;
}

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
Console.WriteLine("TryInvokeMember被調用了,Name:{0}", binder.Name);
bool tryResult = base.TryInvokeMember(binder, args, out result);

return true;
}

#endregion
}

Main方法不變:複製代碼 代碼如下:static void Main(string[] args)
{
dynamic dynProduct = new DynamicProduct();

dynProduct.name = "n1"; //調用TrySetMember方法
dynProduct.Id = 1;
dynProduct.Id = dynProduct.Id + 3;
dynProduct.ShowProduct();

Console.ReadLine();
}

運行,結果如下:

d.P3 = d.M1(d.P1, d.M2(d.P2));

按照從左至右,從裡到外的原則。

1:先調用d.P1,DLR會嘗試調用d 的GetMetaObject 方法,此方法返回一個MyMetaObject對象。

接著DLR知道你調用的是一個屬性,於是它調用返回的MyMetaObject對象的BindGetMember 方法,

輸出為GetMember of property P1

2:調用d.P2,和調用d.P1 一樣.

3:調用d.M2,同樣DLR調用d的GetMetaObject方法,返回一個MyMetaObject對象,接著調用返回對象的BindInvokeMember 方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.