我有一个重载的通用方法,用于获取类型对象的属性值PageData。属性集合被实现为Dictionary<string, object>. 该方法用于避免检查属性是否有null值以及是否有值的繁琐工作。
一种常见的模式是将 的集合绑定PageData到转发器。然后在中继器中每个PageData都是Container.DataItem类型的object。
我针对 PageData 编写了原始扩展方法:
public static T GetPropertyValue<T>(this PageData page, string propertyName);
Run Code Online (Sandbox Code Playgroud)
但是当数据绑定时,你必须将其转换Container.DataItem为PageData:
<%# ((PageData)Container.DataItem).GetPropertyValue("SomeProperty") %>
Run Code Online (Sandbox Code Playgroud)
我有点痒,想知道我是否无法重载扩展对象的方法,将此方法放在单独的命名空间中(以免污染继承的所有内容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") %>
Run Code Online (Sandbox Code Playgroud)
在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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后将调用转发到我期望的PageData版本GetPropertyValue,但是,我得到了 a,StackOverflowException因为它只是重新调用该object版本。
如何让编译器认识到PageData重载比重载更好匹配object?
扩展方法语法只是调用对象静态方法的语法糖。就像调用任何其他常规静态方法一样调用它(如果需要,则转换参数)。
IE,
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);
}
}
Run Code Online (Sandbox Code Playgroud)
根据您的评论,我编写了一个测试程序来查看此行为。看起来它确实采用了最本地化的方法。
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了确保嵌套不会影响任何内容,尝试删除对象重载:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
果然,int调用了重载。
所以我认为,当使用扩展方法语法时,编译器首先在当前命名空间中查找适当的方法(“最本地的”),然后再查找其他可见的命名空间。