Метод расширения C # как реализация интерфейса - PullRequest
42 голосов
/ 28 января 2011

Мне было интересно, может ли метод расширения C # какого-либо класса выступать в качестве реализации интерфейса? Что у меня есть:

Интерфейс:

public interface IEventHandler
{
    void Notify(SEvent ev, IEventEmmiter source);
}

Класс, который его реализует:

class Sim : IEventHandler
{

    /*public void Notify(SEvent ev, IEventEmmiter source)
    {
        Console.WriteLine("Got notified: " + ev.Name);
    }*/

}

И класс, который содержит метод расширения:

public static class ReflectiveEventDispatcher
{
    public static void Notify(this IEventHandler handler, SEvent ev)
    {
        if (handler.GetType().GetMethod("Handle" + ev.Name) != null)
        {
            // C# WTF?
            object[] prms = new object[0];
            prms[0] = ev;
            handler.GetType().GetMethod("Handle" + ev.Name).Invoke(handler, prms);
        }
        else
        {
            throw new System.NotImplementedException("This object doesn't have appropriate handler methods for event " + ev.Name);
        }
    }
}

Теперь я хочу иметь различные классы с интерфейсом IEventHandler, и реализация интерфейсов должна выполняться методом расширения.

Если это невозможно, возможно ли явно определить Уведомление, а затем просто перенаправить вызов в метод расширения?

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

(Надеюсь, это имеет смысл, я привык к Руби, и это доставляет мне действительно тяжелые времена. О, как я скучаю по тебе, мои дорогие миксины ...)

Обновление

Переадресация решена довольно хорошо:

public void Notify(SEvent ev)
{
    ReflectiveEventDispatcher.Notify(this, ev,);
}

Ответы [ 4 ]

25 голосов
/ 28 января 2011

Нет, методы расширения не могут выступать в качестве реализации для интерфейса. Методы расширений являются просто синтаксическим сахаром для статического метода, принимающего экземпляр этого класса в качестве первого параметра, поэтому он не является членом определенного класса, что является требованием для реализации интерфейса.

12 голосов
/ 28 января 2011

это нельзя сделать так, как вы это описываете: разрешение вызова метода C # всегда будет выбирать конкретную реализацию вашего метода, а не метод расширения.

Однако я полагаю, что вы можете получить кое-что, если не определяете метод в интерфейсе, а просто как методы расширения в разных пространствах имен. Конечно, это «статический», так как вызываемый метод все равно будет выбран во время компиляции.

На практике вы выбираете метод, вызываемый с помощью правильной директивы using (аналогично тому, как работает LINQ)

8 голосов
/ 28 января 2011

Это невозможно.

Методы интерфейса должны быть реализованы самим типом реализации.

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

2 голосов
/ 10 октября 2012
var sim = new Sim()
((IEventHandler )sim).Notify(ev)
...