2010-10-07 71 views
0

我有一個重載泛型方法,用於獲取PageData類型的對象的屬性值。屬性集合實現爲Dictionary<string, object>。該方法用於避免檢查屬性是否不是null並且具有值的乏味。強制在C#中使用特定的方法重載

一種常見模式是將PageData的集合綁定到中繼器。然後在中繼器內,每個PageDataContainer.DataItem,其類型爲object

我寫了反對PageData原來的擴展方法:

public static T GetPropertyValue<T>(this PageData page, string propertyName); 

但是數據綁定的時候,你要投的Container.DataItemPageData

<%# ((PageData)Container.DataItem).GetPropertyValue("SomeProperty") %> 

我有點癢癢的,如果我想知道無法重載擴展對象的方法,請將此方法放在單獨的命名空間中(以免污染繼承object的所有內容),並且只在我的aspx/ascx文件中使用此命名空間,我知道我已經綁定了數據收集PageData。藉此,我可以避免在aspx/ascx例如

// The new overload 
public static T GetPropertyValue<T>(this object page, string propertyName); 

// and the new usage 
<%# Container.DataItem.GetPropertyValue("SomeProperty") %> 

裏面的object版本的GetPropertyValue,我投了page參數PageData

public static T GetPropertyValue<T>(this object page, string propertyName) 
{ 
    PageData data = page as PageData; 
    if (data != null) 
    { 
     return data.GetPropertyValue<T>(propertyName); 
    } 
    else 
    { 
     return default(T); 
    } 
} 

,並轉發該呼叫到,我會希望是PageData版本的GetPropertyValue,但是,我m得到StackOverflowException,因爲它只是重新調用object版本。

我怎樣才能讓編譯器意識到PageData過載比object過載更好?

回答

2

擴展方法語法只是調用對象的靜態方法的語法糖。就像調用任何其他常規的靜態方法一樣(如果需要,可以輸入參數)。

public static T GetPropertyValue<T>(this object page, string propertyName) 
{ 
    PageData data = page as PageData; 
    if (data != null) 
    { 
     //will call the GetPropertyValue<T>(PageData,string) overload 
     return GetPropertyValue<T>(data, propertyName); 
    } 
    else 
    { 
     return default(T); 
    } 
} 

[編輯]

在您的評論的光,我寫了一個測試程序,看看此行爲。它看起來確實符合最本地的方法。

using System; 
using Test.Nested; 

namespace Test 
{ 
    namespace Nested 
    { 
     public static class Helper 
     { 
      public static void Method(this int num) 
      { 
       Console.WriteLine("Called method : Test.Nested.Helper.Method(int)"); 
      } 
     } 
    } 

    static class Helper 
    { 
     public static void Method(this object obj) 
     { 
      Console.WriteLine("Called method : Test.Helper.Method(object)"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      int x = 0; 
      x.Method(); //calls the object overload 
      Console.Write("Press any key to continue . . . "); 
      Console.ReadKey(true); 
      Console.WriteLine(); 
     } 
    } 
} 

要確保嵌套並不影響什麼,想這也刪除對象重載:

足夠
using System; 
using Test.Nested; 

namespace Test 
{ 
    namespace Nested 
    { 
     public static class Helper 
     { 
      public static void Method(this int num) 
      { 
       Console.WriteLine("Called method : Test.Nested.Helper.Method(int)"); 
      } 
     } 
    } 

    static class Helper 
    { 
     public static void Method(this string str) 
     { 
      Console.WriteLine("Called method : Test.Helper.Method(string)"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      int x = 0; 
      x.Method(); //calls the int overload 
      Console.Write("Press any key to continue . . . "); 
      Console.ReadKey(true); 
      Console.WriteLine(); 
     } 
    } 
} 

肯定的是,int過載被調用。

所以我認爲只是在使用擴展方法語法時,編譯器首先在當前名稱空間內查找合適的方法(「最本地」),然後查看其他可見名稱空間。

+0

是的,我發現這個工作。謝謝。 – 2010-10-07 08:55:57

+0

@Greg B:在這種情況下,擴展方法的語法也應該起作用。我建議你再看一遍,因爲你可能會發現一些實際上很重要的潛在原因。 – 2010-10-07 08:58:14

+0

爲了冒險猜測,可能擴展方法是在不同名稱空間的不同類中定義的,並且期望的重載不在範圍內。它應該起作用,因爲'data'的類型是'PageData',如果可用的話編譯器會選擇它。 – 2010-10-07 09:10:00

1

它應該已經正常工作。我在下面列出了一個簡短但完整的例子。我建議你仔細檢查你的方法簽名和調用,如果你仍然有問題,試着想出一個類似的短而完整的程序來編輯你的問題。我嫌疑人你會找到答案,同時提出的程序,但至少如果你不這樣做,我們應該能夠重現並修復它。

using System; 

static class Extensions 
{ 
    public static void Foo<T>(this string x) 
    { 
     Console.WriteLine("Foo<{0}>(string)", typeof(T).Name); 
    } 

    public static void Foo<T>(this object x) 
    { 
     Console.WriteLine("Foo<{0}>(object)", typeof(T).Name); 
     string y = (string) x; 
     y.Foo<T>(); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     object s = "test"; 
     s.Foo<int>(); 
    } 
} 
+0

@Jon在你稱爲'Foo (y)的對象的'Foo'中;'作爲一個正常的靜態方法。這是不同的,因爲我的代碼將其稱爲擴展方法。例如'y.Foo ();' – 2010-10-07 08:50:36

+0

@Greg - 我從你的帖子中獲取了代碼,爲PageData版本的擴展方法添加了一個實現,然後調用了對象版本(作爲擴展方法),並且與Jon的例如,它工作正常。所以它不是關於擴展方法,據我所知。 – 2010-10-07 08:53:31

+0

@Jon是的,在靜態窗體中調用它,將其稱爲「PageData」實例的擴展,導致了StackOverflow。 – 2010-10-07 08:54:49