C # 3.5 DLR Expression. Динамический вопрос - PullRequest
3 голосов
/ 25 января 2010

Я унаследовал небольшой язык сценариев и пытаюсь перенести его на DLR, чтобы им было немного легче управлять. До сих пор это было довольно просто. Я столкнулся с проблемой, хотя пытался динамически вызывать члены переменной. Текущий язык работает на .NET и использует для этого цикл синтаксического анализа и отражения, но я надеялся уйти от этого. Вот пример языка сценария:

string $system1RemoteUri;
string $dbconnection = $config.GetDBConnection ("somedb");
float $minBad = 0.998;
float $minGood = 0.2;

$ systen1RemoteURI, $ minBad и $ minGood - это переменные, которые будут установлены в скрипте вместе с $ dbconnection. Однако $ dbconnection получит свое значение из переменной, переданной в $ config. 4 переменные должны быть доступны вызывающей стороне, поэтому они передаются в лямбду, изначально как ноль. Вот сгенерированный Lambda IL (представление отладки):

.Lambda #Lambda1<Delegate6$1>(
    System.String& $$system1RemoteUri,
    System.String& $$dbconnection,
    System.Double& $$minBad,
    System.Double& $$minGood
    System.Object $$config) {
    .Block() {
        $$minBad = 0.998D;
        $$minGood = 0.2D
    }

    //Some assignment similar to...
    //.Dynamic Call GetDBConnection($config, "somedb");
}

Я пытаюсь понять, как использовать Expression.Dynamic для генерации $ config.GetDBConnection ("somedb"). Глядя на примеры в библиотеках Sympl, я считаю, что испускаемый IL должен выглядеть следующим образом: .Dynamic Вызов GetdbConnection ($ config, "somedb"), но я не могу понять, как на самом деле испустить это из Expression.Dynamic.

Кажется, что требуется CallSiteBinder, который я не могу создать правильно, и я не понимаю, каков порядок параметров Expression.Dynamic, так как кажется, что требуется вызывать только "member", а не основание.

Я не знаю тип времени выполнения $ config, это просто какой-то объект, который реализует функцию с именем GetDBConnection (string). Это не обеспечивается интерфейсом или базовым классом.

Любая помощь будет оценена.

1 Ответ

4 голосов
/ 26 января 2010

Вы можете либо превратить это в InvokeMemberBinder, либо превратить «$ config.GetDBConnection» в GetMember, а затем выполнить Invoke для результата передачи $ someDb в качестве аргумента.

Для реализации ваших GetMemberBinder и InvokeMemberBinder вы можете использовать класс DefaultBinder внешнего слоя DLR. В последнем исходном коде IronPython / IronRuby вы можете просто создать новый экземпляр DefaultBinder из ничего. Затем в вашем FallbackGetMember / FallbackInvoke вы можете вызвать defaultBinder.GetMember (...) и defaultBinder.Call (который следует переименовать в Invoke). Это будет иметь дело с большинством типов .NET для вас. Также все объекты, которые реализуют IDynamicMetaObjectProvider, будут работать с ним также. Для других динамических операций вы можете использовать другие методы в связывателе по умолчанию. И если вы хотите начать настраивать разрешение перегрузки и правила привязки, у него есть множество ручек, которые вы можете включить.

К сожалению, связыватель по умолчанию не имеет реализации InvokeMemberBinder прямо сейчас, так что вам, вероятно, лучше w / GetMember / Invoke.

...