.NET 4.0 Динамический объект используется статически? - PullRequest
1 голос
/ 06 мая 2010

Я задал еще один связанный с этим вопрос здесь: приведение динамической проблемы к статической

Я устал от файлов конфигурации XML в .NET и хочу заменить их форматом, более разумным. Поэтому я пишу синтаксический анализатор конфигурационных файлов для приложений C #, который примет пользовательский формат файла конфигурации, проанализирует его и создаст исходную строку Python, которую затем можно будет выполнить в C # и использовать в качестве объекта static (да, верно - Мне нужен объект static (не статический тип dyanamic) в конце).

Вот пример того, как выглядит мой конфигурационный файл:

// my custom config file format
GlobalName: ExampleApp

Properties
{
    ExternalServiceTimeout: "120"
}

Python 
{
    // this allows for straight python code to be added to handle custom config
    def MyCustomPython:
     return "cool"
}

Использование ANTLR Я создал Lexer / Parser, который преобразует этот формат в скрипт Python. Итак, предположим, что у меня все в порядке, и я могу взять .config выше и запустить на нем свой Lexer / Parser, чтобы получить скрипт Python обратно (это дает дополнительное преимущество, предоставляя мне инструмент проверки для моей конфигурации). Запустив результирующий скрипт в C #

// simplified example of getting the dynamic python object in C#
// (not how I really do it)
ScriptRuntime py = Python.CreateRuntime(); 
dynamic conf = py.UseFile("conftest.py");
dynamic t = conf.GetConfTest("test");

Я могу получить dynamic объект, который имеет мои настройки конфигурации. Теперь я могу получить настройки моего конфигурационного файла в C #, вызвав динамический метод для этого объекта:

//C# calling a method on the dynamic python object
var timeout = t.GetProperty("ExternalServiceTimeout");
//the config also allows for straight Python scripting (via the Python block)
var special = t.MyCustonPython();

Конечно, у меня нет безопасности типов и нет поддержки intellisense. У меня есть dynamic представление моего конфигурационного файла, но я хочу статический. Я знаю , каков тип моего объекта Python - он фактически обновляется в экземпляре класса C #. Но так как это происходит в python, это тип не типа C #, а dynamic. Что я хочу сделать, так это затем привести объект обратно к типу C # , который, как я знаю, является :

// doesn't work--can't cast a dynamic to a static type (nulls out)
IConfigSettings staticTypeConfig = t as IConfigSettings

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

Итак, вот моя текущая тактика: поскольку я знаю тип объекта python, я создаю класс-оболочку C #:

public class ConfigSettings : IConfigSettings

, который принимает dynamic объект в ctor:

    public ConfigSettings(dynamic settings)
    {
        this.DynamicProxy = settings;
    }

    public dynamic DynamicProxy
    {
        get;
        private set;
    }

Теперь у меня есть ссылка на динамический объект Python, тип которого я знаю. Поэтому я могу просто поместить обертки вокруг методов Python, которые, как я знаю, существуют:

// wrapper access to the underlying dynamic object
// this makes my dynamic object appear 'static' 
public string GetSetting(string key)
{
    return this.DynamicProxy.GetProperty(key).ToString();
}

Теперь доступ к динамическому объекту осуществляется через этот статический прокси-сервер, и, следовательно, его можно передавать в статический мир C # через интерфейс и т. Д .:

// dependency inject the dynamic object around
IBusinessLogic logic = new BusinessLogic(IConfigSettings config);

Это решение обладает всеми преимуществами статической типизации, которую мы знаем и любим, и в то же время дает мне возможность «спешить» с динамикой:

// the DynamicProxy property give direct access to the dynamic object
var result = config.DynamicProxy.MyCustomPython();

но, чувак, это кажется довольно запутанным способом добраться до объекта, который в первую очередь является статическим типом! Поскольку весь мир динамического / статического взаимодействия для меня нов, я действительно вопрос о том, является ли мое решение оптимальным или я что-то упускаю (то есть какой-то способ приведения этого динамического объекта к известному статическому типу) о том, как преодолеть пропасть между этими двумя вселенными.

Ответы [ 3 ]

0 голосов
/ 17 сентября 2010

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

0 голосов
/ 14 марта 2011

Фреймворк с открытым исходным кодом Импровизированный интерфейс позволяет вам объявить статический интерфейс c # и обернуть любой динамический объект.

0 голосов
/ 06 мая 2010

Если «IConfigSettings staticTypeConfig = t as IConfigSettings» не работает, то у вас фактически нет объекта, реализующего IConfigSettings. Предполагая, что вы объявляете класс в Python, вы должны обязательно включить интерфейс в список базовых классов, например:

class C(IConfigSettings):
   def SomeIConfigSettingsMember(self): pass

Если это не сработает, это может помочь, если вы также разместите код Python.

...