Я экспериментирую с DynamicObject
. Одна из вещей, которые я пытаюсь сделать, устанавливает значения ref
/out
аргументы, как показано в коде ниже. Однако я не могу иметь значения i
и j
в Main()
набор правильно (даже при том, что они установлены правильно в TryInvokeMember()
). Делает любой знает, как назвать a DynamicObject
объект с ref
/out
аргументы и смочь получить набор значений в методе?
class Program
{
static void Main(string[] args)
{
dynamic proxy = new Proxy(new Target());
int i = 10;
int j = 20;
proxy.Wrap(ref i, ref j);
Console.WriteLine(i + ":" + j); // Print "10:20" while expect "20:10"
}
}
class Proxy : DynamicObject
{
private readonly Target target;
public Proxy(Target target)
{
this.target = target;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
int i = (int) args[0];
int j = (int) args[1];
target.Swap(ref i, ref j);
args[0] = i;
args[1] = j;
result = null;
return true;
}
}
class Target
{
public void Swap(ref int i, ref int j)
{
int tmp = i;
i = j;
j = tmp;
}
}
Обновление 7/15: Microsoft утверждает, что устранила проблему для следующего выпуска.NET http://connect.microsoft.com/VisualStudio/feedback/details/543101/net-4-0s-dynamicobject-doesn-t-set-ref-out-arguments
Обновление 08.09.2012: Протестированное использование VS.NET 2012 и с.NET 4.0 и с 4.5, подтвердите: это уже фиксируется.
Похоже, что могла быть ошибкой - вероятно, в DynamicObject
. Если вы добавите метод Wrap
к Proxy
следующим образом:
public void Wrap(ref int x, ref int y)
{
target.Swap(ref x, ref y);
}
Тогда, даже если он по-прежнему вызывается динамически (т.е. код в Main
остается прежним) код работает ... так что, по крайней мере, общий уровень «как работает динамический объект» поддерживает передачу по ссылке.
Я подозреваю, что если это действительно ошибка в DLR, может быть уже слишком поздно исправлять .NET 4, но в любом случае стоит сообщить о Connect , чтобы это могло быть исправлено в сервис-паке. В качестве альтернативы, если это преднамеренное ограничение / ограничение, оно должно быть четко задокументировано в MSDN (чего, насколько я понимаю, на данный момент нет).
Короче говоря, DynamicObject не поддерживает передачу по ссылке, поэтому то, что вы хотите сделать, напрямую невозможно.
Это не ошибка. Как уже было сказано здесь, DynamicObject не поддерживает параметры ref и out в TryInvokeMember. Все, что передается в этот метод, обрабатывается «по значению». Вкратце, метод TryInvokeMember просто игнорирует эти ключевые слова, и поэтому ваш метод не работает.
Если вы последуете предложению Джона Скита и создадите свой собственный метод Wrap в классе, унаследованном от DynamicObject, это будет немного другой сценарий. Рабочий процесс выглядит следующим образом: при вызове метода для DynamicObject связыватель времени выполнения C # сначала ищет метод в самом классе. Если он может его найти, он вызывает этот метод. На этом этапе информация о параметрах «ref» и «out» все еще сохраняется. Если он не может найти такой метод, он вызывает метод TryInvokeMember и просто выдает информацию о ключевых словах «ref» и «out» и начинает обрабатывать все как «по значению». Помните, что DynamicObject должен поддерживать взаимодействие с другим языком, который может не иметь всех функций C #.
Правда, в документации сейчас отсутствует информация о «ref» и «out». Я добавлю его в следующее обновление документации.