2010-10-07 84 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