Я задал еще один связанный с этим вопрос здесь: приведение динамической проблемы к статической
Я устал от файлов конфигурации 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();
но, чувак, это кажется довольно запутанным способом добраться до объекта, который в первую очередь является статическим типом! Поскольку весь мир динамического / статического взаимодействия для меня нов, я действительно вопрос о том, является ли мое решение оптимальным или я что-то упускаю (то есть какой-то способ приведения этого динамического объекта к известному статическому типу) о том, как преодолеть пропасть между этими двумя вселенными.