在C#中强制使用方法的特定重载

时间:2010-10-07 08:41:26

标签: c#-3.0

我有一个重载的泛型方法,用于获取类型为PageData的对象的属性值。属性集合实现为Dictionary<string, object>。该方法用于避免繁琐检查属性是否为null并且具有值。

一种常见的模式是将PageData的集合绑定到转发器。然后在转发器中,每个PageData都是Container.DataItem,类型为object

我针对PageData写了原始的扩展方法:

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

但是在绑定数据时,您必须将Container.DataItem转换为PageData

<%# ((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版本的StackOverflowException,但是,我正在获得object,因为它只是重新调用{{ 1}}版本。

如何让编译器意识到PageData重载比object重载更好?

2 个答案:

答案 0 :(得分: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重载。

所以我认为只是在使用扩展方法语法时,编译器首先在当前命名空间中查找适当的方法(“最本地”),然后查找其他可见的命名空间。

答案 1 :(得分: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>();
    }
}