Принудительное использование определенной перегрузки метода в C # - PullRequest
0 голосов
/ 07 октября 2010

У меня есть перегруженный универсальный метод, используемый для получения значения свойства объекта типа 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 версию.

Как заставить компилятор понять, что перегрузка PageData лучше, чем перегрузка object?

Ответы [ 2 ]

2 голосов
/ 07 октября 2010

Синтаксис метода расширения является просто синтаксическим сахаром для вызова статических методов на объектах.Просто назовите его так, как если бы вы использовали любой другой обычный статический метод (при необходимости приводя аргументы).

, т.е.

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);
    }
}

[edit]

В светеВаш комментарий, я написал тестовую программу, чтобы увидеть это поведение.Похоже, что он работает с наиболее локальным методом.

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 голос
/ 07 октября 2010

Это уже должно работать нормально.Я включил короткий, но полный пример ниже.Я предлагаю вам еще раз проверить подписи и вызовы вашего метода, и, если у вас все еще есть проблемы, попробуйте найти аналогичную короткую, но полную программу для редактирования вашего вопроса.Я подозреваю, вы найдете ответ при разработке программы, но, по крайней мере, если вы этого не сделаете, мы сможем воспроизвести и исправить это.

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>();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...