Тип возврата DLR

Мне нужна помощь DLR. Я реализую IDynamicMetaObjectProvider и DynamicMetaObject, но у меня возникают некоторые проблемы с получением ожидаемого типа возврата. Я перекрываю BindInvokeMember в метаобъекте, я вижу все типы аргументов, но не возвращаемый тип. Кто-нибудь знает, как я к этому доберусь, если возможно? Я знаю, что тип возвращаемого значения является динамическим, но что, если вызываемая вами вещь зависит от типа возвращаемого значения. Я не знаю, какое действие выполнять в DynamicMetaObject, если не знаю тип возвращаемого значения, которого ожидает потребитель.

Обновление два

Я не могу вставить сюда свой реальный код, так как он вызывает все виды работы. Ниже приведен пример кода динамического объекта.

public class TestDynamicMetaObject : DynamicMetaObject
{
    public TestDynamicMetaObject(Expression expression, object value)
        : base (expression, BindingRestrictions.Empty, value)
    {
    }

    public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
    {
        Delegate method = new Func<int>(Test);
        return new DynamicMetaObject(
            Expression.Call(method.Method),
            BindingRestrictions.GetInstanceRestriction(Expression,Value),
            Value
        );
    }

    public static int Test()
    {
        return 10;
    }

}
public class TestDynamicObject : IDynamicMetaObjectProvider
{
    DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
    {
        return new TestDynamicMetaObject(parameter, this);
    }
}

Вот где я использую.

static void Main(string[] args)
{
    try
    {
        dynamic x = new TestDynamicObject();
        int gg= x.Test();
        Console.WriteLine(gg);
    }
    catch (Exception excep)
    {
        Console.WriteLine(excep);
    }
    Console.ReadLine();
}

Вот код, который создает компилятор.

private static void Main(string[] args)
{
    try
    {
        object x = new TestDynamicObject();
        if (<Main>o__SiteContainer0.<>p__Site1 == null)
        {
            <Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, int>>.Create(new CSharpConvertBinder(typeof(int), CSharpConversionKind.ImplicitConversion, false));
        }
        if (<Main>o__SiteContainer0.<>p__Site2 == null)
        {
            <Main>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object>>.Create(new CSharpInvokeMemberBinder(CSharpCallFlags.None, "Test", typeof(Program), null, new CSharpArgumentInfo[] { new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) }));
        }
        Console.WriteLine(<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, <Main>o__SiteContainer0.<>p__Site2.Target(<Main>o__SiteContainer0.<>p__Site2, x)));
    }
    catch (Exception excep)
    {
        Console.WriteLine(excep);
    }
    Console.ReadLine();
}

person AbdElRaheim    schedule 01.09.2009    source источник


Ответы (2)


Для стандартных двоичных файлов, которые возвращают что-то, тип возвращаемого значения почти всегда является объектом (получение, установка, операции и т. Д.). В противном случае он недействителен для стандартных привязок (например, DeleteMember).

Вы также можете получить ожидаемый тип возвращаемого значения во время выполнения из свойства ReturnType входящего связывателя.

person Dino Viehland    schedule 01.09.2009
comment
на входящей подшивке нет возвращаемого типа. Похоже, что методы, вызываемые динамическими объектами, всегда возвращают динамический тип, следовательно, объект. Компилятор генерирует некоторый код преобразования. - person AbdElRaheim; 01.09.2009
comment
Что вы имеете в виду, что у входящей подшивки нет типа возврата? Если вы имеете в виду, что свойства ReturnType нет, у вас старые источники. Вы можете видеть, что это свойство явно живет здесь: dlr.codeplex.com/SourceControl/changeset / view / 27223 # 581318 В обязанности DynamicMetaObject входит обеспечение соответствия типа, возвращаемого созданным выражением, стандартным связывателям. Что касается преобразования в динамический - вам не нужно преобразовывать в динамический. Динамические объекты всегда вводятся в объект с дополнительными метаданными, которые говорят, что они динамические. - person Dino Viehland; 01.09.2009
comment
Да, я вижу недвижимость на кодеплексе. Его нет в бета-версиях 1, которые я использую. Думаю, мне придется дождаться следующего обновления vs2010. Под преобразованием я подразумеваю, что приведенный ниже код также использует преобразование. Я помню, как где-то читал, что метод динамических объектов возвращает объекты и их нужно преобразовать. Это не так? Код, сгенерированный компилятором, находится в моем посте выше. Изменилось ли это также в последних битах? объект x = новый DynamicTest (); int w = x.Test (); - person AbdElRaheim; 02.09.2009
comment
Никаких преобразований быть не должно. Динамический объект - это просто объект с атрибутом, который говорит, что он динамический. В опубликованном коде похоже, что у вас есть приведение к int в коде C #. Если результатом вашего InvokeMember не является IDO, вы никогда не увидите вызов Convert самостоятельно - вместо этого связыватель C # будет обрабатывать преобразование для обычных типов .NET. Если это все еще не дает ответа на вопрос, вы можете опубликовать свой код C # и свою реализацию DynamicMetaObject. - person Dino Viehland; 02.09.2009
comment
Сам не делаю гипс. Я обновил сообщение, включив в него код. Опять же, это vs2010 beta 1, поэтому в последних битах поведение могло измениться. - person AbdElRaheim; 03.09.2009
comment
Если вы измените Test на возврат TestDynamicObject вместо int, вы увидите запрос на преобразование. Поскольку здесь вы возвращаете нединамический объект, C # просто выполняет обычную семантику преобразования. В этом случае значение уже является int, поэтому преобразование не требуется. Если вместо этого вы вернете double, то C # выполнит обычное преобразование из double в C #. - person Dino Viehland; 09.09.2009
comment
Вы также можете просто вернуть это; из BindInvokeMember, и тогда вы увидите, что преобразование тоже произошло. - person Dino Viehland; 09.09.2009
comment
переход от объекта к int обычно не является семантикой преобразования. Наоборот :) Итак, нет никакого способа увидеть, какой тип ожидает потребитель? Метод тестирования - это просто метод тестирования. То, что я на самом деле вызываю, я передаю в качестве параметра ожидаемого возвращаемого типа, поэтому я не могу сделать динамический. - person AbdElRaheim; 10.09.2009
comment
Когда он динамически переходит от объекта (в рамке int) к int, то это обычная семантика преобразования. Единственный способ увидеть преобразование - это если преобразованный объект является динамическим. Если вам абсолютно необходимо это увидеть, просто создайте ConvertibleObject, который является IDynamicMetaObjectProvider, который реализует BindConvert. Затем вы можете просто обернуть любое возвращаемое значение в свой ConvertibleObject, распаковать значение и увидеть преобразование. - person Dino Viehland; 10.09.2009

Похоже, что тип возвращаемого значения, по крайней мере, это бета-версия, которую я использовал, не знает ...

Я пытался создать пример ap / invoke с использованием DLR, но похоже, что это невозможно, если вы не передадите ожидаемый тип возвращаемого значения в качестве параметра, который я в конечном итоге сделал: \ Это кажется мне ограничением ... Надеюсь, это будут рассмотрены в будущем.

person Ziad    schedule 11.12.2009