Как применить метод расширения к объекту, имеющему тип ExpandoObject?

Вот мой код:

public static class DynamicExtensions

    public static void Add(this ExpandoObject obj, string path){
        dynamic _obj = obj;
        if (_obj == null) throw new ArgumentNullException("obj");
        _obj.path = path;
    }
}

Но я получил ошибку «'System.Dynamic.ExpandoObject' не содержит определения для 'Добавить'», когда я вызываю это таким образом:

dynamic obj = new ExpandoObject();
obj.Add("p1");

Как это исправить?

Заранее спасибо!


person zs2020    schedule 19.09.2012    source источник
comment
@JaneDoe Да, код компилируется. Я думаю, что компилятор не может определить, является ли Add динамическим методом или методом расширения.   -  person zs2020    schedule 19.09.2012
comment
возможный дубликат метода расширения и динамического объекта в C #   -  person nawfal    schedule 20.07.2014


Ответы (2)


Проблема заключается в использовании dynamic с методами расширения - они просто несовместимы. Это было бы хорошо:

ExpandoObject obj = new ExpandoObject();
obj.Add("p1");

... но с dynamic нет поддержки методов расширения.

Из раздела 7.6.5.2 спецификации C # 5:

При вызове метода (§7.5.5.1) одной из форм

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )

если обычная обработка вызова не находит применимых методов, делается попытка обработать конструкцию как вызов метода расширения. Если expr или какой-либо из аргументов имеет динамический тип времени компиляции, методы расширения применяться не будут.

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

person Jon Skeet    schedule 19.09.2012

Dynamic явно исключает методы расширения. Это потому, что метод разрешается во время выполнения, а не во время компиляции. Чтобы правильно разрешить вызов метода, DLR потребуется информация о вызове, который включает в себя действующие директивы using; для этого нет механизма. Подробнее см. Этот ответ Эрика Липперта: https://stackoverflow.com/a/5313149/385844

Конечно, вы можете вызвать метод, используя синтаксис вызова статического метода:

DynamicExtensions.Add(obj, "p1");
person phoog    schedule 19.09.2012
comment
Другой способ обойти ограничение, которое может оказаться полезным: ((ExpandoObject)a).Add("p1"). (Может показаться, что компилятору вообще не нужна эта `` подсказка ''; но помните, что, за исключением очень тривиальных случаев, компилятор не знает до времени выполнения, существует ли метод с именем Add для динамического объекта сам!) - person MikeBeaton; 12.09.2016