【问题标题】:.NET 4.0 Dynamic object used statically?.NET 4.0 静态使用的动态对象?
【发布时间】:2010-05-06 18:51:19
【问题描述】:

我在这里提出了另一个相关问题:casting dynamic to static problem

我已经厌倦了 .NET 中的 XML 配置文件,想用一种更合理的格式替换它们。因此,我正在为 C# 应用程序编写一个配置文件解析器,它将采用自定义配置文件格式,解析它,并创建一个 Python 源字符串,然后我可以在 C# 中执行并用作 static 对象(是的,没错--最后我想要一个static(不是静态类型的动态)对象)。

这是我的配置文件的示例:

// 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 我创建了一个词法分析器/解析器,可以将此格式转换为 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();

当然,我这里没有类型安全,也没有智能感知支持。我有一个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

在ctor中接受dynamic对象:

    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();

但是,伙计,这似乎是首先获取静态类型对象的复杂方式!因为整个动态/静态交互世界对我来说都是新的,所以我真的质疑我的解决方案是否是最佳的,或者我是否遗漏了一些关于如何弥合这两个宇宙之间的鸿沟的东西(即将动态对象转换为已知静态类型的某种方式)。

【问题讨论】:

  • 这似乎并不比 XML 更理智。只是说...
  • 我认为你把引擎和 .config 文件本身弄糊涂了…… .config 文件本身就更理智了,恕我直言。

标签: dynamic c#-4.0 dynamic-language-runtime


【解决方案1】:

如果“IConfigSettings staticTypeConfig = t as IConfigSettings”不起作用,那么您实际上并没有实现 IConfigSettings 的对象。假设您在 Python 中声明该类,您应该确保将接口包含在基类列表中,例如:

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

如果这不起作用,那么如果您也发布 Python 代码可能会有所帮助。

【讨论】:

  • 嗯。我不明白我做错了什么。我只是尝试使用 python 更新并返回 System.Uri 对象,我可以将它在 C# 中转换为 System.Uri。但我无法让它与我自己的类型一起使用。
  • 我把它分成另一个更具体的问题,因为我没有得到这个工作:stackoverflow.com/questions/2785252/…
【解决方案2】:

请参阅此处的拆分问题C# 4.0: casting dynamic to static,它提供了一种实现此功能的方法。

【讨论】:

    【解决方案3】:

    开源框架impromptu interface 允许您声明一个静态 c# 接口并包装任何动态对象。

    【讨论】:

      猜你喜欢
      • 2011-05-28
      • 1970-01-01
      • 2011-02-16
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 2012-09-22
      • 1970-01-01
      相关资源
      最近更新 更多