草庐IT

C# 4.0 : casting dynamic to static

coder 2024-05-28 原文

这是一个分支问题,与我问的另一个问题有关 here .我把它分开是因为它真的是一个子问题:

我在转换 dynamic 类型的对象时遇到困难到另一个(已知的)静态类型。

我有一个用于执行此操作的 IronPython 脚本:

import clr
clr.AddReference("System")
from System import *

def GetBclUri():
    return Uri("http://google.com")

请注意,它只是 更新 BCL System.Uri 类型并返回它 .所以我知道静态类型 返回的对象。

现在在 C# 领域,我正在更新脚本托管内容并调用这个 getter 来返回 Uri 对象:
dynamic uri = scriptEngine.GetBclUri();
System.Uri u = uri as System.Uri; // casts the dynamic to static fine

工作没问题。我现在可以使用强类型 Uri 对象,就像它最初是静态实例化的一样。

然而....

现在我想定义我自己的 C# 类,就像我对 Uri 所做的那样,它将在动态领域中进行更新。我的简单 C# 类:
namespace Entity
{
    public class TestPy // stupid simple test class of my own
    {
        public string DoSomething(string something)
        {
            return something;
        }
    }
}

现在在 Python 中,新建一个这种类型的对象并返回它:
sys.path.append(r'C:..path here...')
clr.AddReferenceToFile("entity.dll")
import Entity.TestPy

def GetTest():
    return Entity.TestPy(); // the C# class

然后在 C# 中调用 getter:
dynamic test = scriptEngine.GetTest();
Entity.TestPy t = test  as Entity.TestPy; // t==null!!!

在这里,类型转换不起作用。请注意,'test' 对象(动态)是有效的——我可以调用 DoSomething()——它只是不会转换为已知的静态类型
string s = test.DoSomething("asdf"); // dynamic object works fine

所以我很困惑。 BCL 类型 System.Uri 将从动态类型转换为正确的静态类型,但我自己的类型不会。显然有一些我不明白的东西......

——

更新:我做了一堆测试,以确保我的程序集引用都正确排列。我更改了引用的程序集版本号,然后查看了 dynamic C# 中的对象 GetType() 信息——它是正确的版本号,但它仍然不会转换回已知的静态类型。

然后我在我的控制台应用程序中创建了另一个类来检查我是否会得到相同的结果,结果是肯定的:我可以得到 dynamic在 C# 中引用在我的 Python 脚本中实例化的静态类型,但它不会正确转换回已知的静态类型。

——

更多信息:

Anton 在下面建议 AppDomain 程序集绑定(bind)上下文可能是罪魁祸首。经过一些测试,我认为很有可能是。 . .但我不知道如何解决它!我不知道程序集绑定(bind)上下文,所以多亏了 Anton,我对程序集分辨率和出现的细微错误有了更多的了解。

所以我通过在启动脚本引擎之前在 C# 中放置一个事件处理程序来观察程序集解析过程。这让我可以看到 python 引擎启动和运行时开始解析程序集:
private static Type pType = null; // this will be the python type ref

// prior to script engine starting, start monitoring assembly resolution
AppDomain.CurrentDomain.AssemblyResolve 
            += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

... 并且处理程序设置 var pType 到 python 正在加载的类型 :
static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{

    if (args.LoadedAssembly.FullName == 
        "Entity, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null")
    {
        // when the script engine loads the entity assembly, get a reference
        // to that type so we can use it to cast to later.
        // This Type ref magically carries with it (invisibly as far as I can 
        // tell) the assembly binding context
        pType = args.LoadedAssembly.GetType("Entity.TestPy");
    }
}

因此,虽然 python 使用的类型在 C# 中是相同的,但我认为(如 Anton 所提议的)不同的绑定(bind)上下文意味着对于运行时,这两种类型(“加载绑定(bind)上下文”中的一种和'loadfrom 绑定(bind)上下文) 是不同的——所以你不能转换到另一个。

所以现在我已经掌握了 Python 加载的类型(以及它的绑定(bind)上下文),瞧,在 C# 中,我可以将动态对象转换为这个静态类型并且它可以工作:
dynamic test = scriptEngine.GetTest();
var pythonBoundContextObject = 
       Convert.ChangeType(test, pType); // pType = python bound

string wow = pythonBoundContextObject .DoSomething("success");

但是,唉,这并不能完全解决问题,因为 var pythonBoundContextObject而正确的类型,仍然带有错误的程序集绑定(bind)上下文的污点 .这意味着我不能把它传递给我代码的其他部分,因为我们还有这个 奇怪的类型不匹配绑定(bind)上下文的无形幽灵让我感到寒冷。
// class that takes type TestPy in the ctor... 
public class Foo
{
    TestPy tp;

    public Foo(TestPy t)
    {
        this.tp = t;
    }
}

// can't pass the pythonBoundContextObject (from above): wrong binding context
Foo f = new Foo(pythonBoundContextObject); // all aboard the fail boat

因此,解决方案必须在 Python 端:让脚本加载到正确的程序集绑定(bind)上下文中。

在 Python 中,如果我这样做:
# in my python script
AppDomain.CurrentDomain.Load(
    "Entity, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null");

运行时无法解析我的类型:
import Entity.TestPy #fails

最佳答案

以下是 IronPython 团队的回答,其中涵盖了相同的问题:

C# / IronPython Interop with shared C# Class Library

(摘自 http://lists.ironpython.com/pipermail/users-ironpython.com/2010-September/013717.html)

关于C# 4.0 : casting dynamic to static,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2785252/

有关C# 4.0 : casting dynamic to static的更多相关文章

  1. ruby-on-rails - 从 Rails 2.3 升级到 Rails 4.0 - 2

    我们有一个目前在Rails2.3.12版和Ruby1.8.7版上运行的应用程序。我们想将我们的应用程序更新到Rails4.0和Ruby2.1.0。我们有大约200个模型和150个Controller。我想知道升级过程需要多大的努力。您还可以提供升级可以遵循的步骤。我们应该先升级Ruby然后再升级Rails还是相反? 最佳答案 您想要实现的目标将是史诗般的努力。我无法为您提供分步说明,因为不可能在一个答案中涵盖所有情况。我建议不要同时升级Ruby和Rails,而是分步升级。升级本身的复杂性是巨大的,但只要您的应用程序具有合理的测试覆盖

  2. ruby-on-rails - Rails 4.0 中的路由、路径助手和 STI - 2

    这让我发疯!我有两个模型Lion和Cheetah。两者都继承自Wildcat。classWildcat这里用的是STI。它们都通过ControllerWildcatsController进行处理。在那里,我有一个before_filer从params[:type]和所有其他东西中获取wildcat的type以使用正确的类.在我的routes.rb中,我创建了以下路线:resources:lions,controller:'wildcats',type:'Lion'resources:cheetahs,controller:'wildcats',type:'Cheetah'如果我现在想使

  3. ruby-on-rails - rails 4.0 上的 haml-rails? - 2

    我想知道是否有人在使用Rails4.0中的haml-railsgem时遇到过任何问题。有一个RailsCast那说有一些问题,但没有更多提及这一点。托管在GitHub上的gem也没有明确提及对Rails4.0的支持。那么这方面的进展如何? 最佳答案 我在Rails4项目中使用haml-rails(0.4),一切正常 关于ruby-on-rails-rails4.0上的haml-rails?,我们在StackOverflow上找到一个类似的问题: https:/

  4. ruby-on-rails - rails 4.0 中为删除操作创建 link_to 的问题 - 2

    这是我在Rails中的第一个项目,即创建一个表来存储有关游戏的数据。我能够显示表格中有关获胜者得分、失败者得分等的数据。但是,我的表格列存在问题,其中包含每个游戏的删除链接。这是我在游戏Controller中删除方法的代码:defdelete@game=Game.find(params[:game])@game.destroy()redirect_to:action=>'index'end我的表格代码片段,其中包括link_to命令的行在我调用的路由文件中resources:games据我所知,这有助于生成基本路由。谁能帮我弄清楚为什么我的link_to不起作用?

  5. ruby-on-rails - bcrypt 错误 : Devise ruby 2. 0 和 rails 4.0 - 2

    当我尝试运行我的应用程序时,我不断收到此错误:C:/ruby-2.0.0-p195-i386-mingw32/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0.rc1/lib/active_support/dependencies.rb:228:in`require':无法加载此类文件--2.0/bcrypt_ext(加载错误)有人要吗?-我正在尝试使用设计gem进行基本用户身份验证.. 最佳答案 我在Windows上更新到Ruby2.0.0+时遇到了这个错误。我能够通过卸载下载的所有版本的b

  6. ruby-on-rails - Rails 4.0 expire_fragment/缓存过期不起作用 - 2

    我一直在尝试使用Rails的缓存功能,但我无法使某些缓存片段过期,尽管它们似乎已过期。使用Rails教程站点中指出的“俄罗斯娃娃缓存”,我正在使用此配置我在release_controller.rbController中使外部缓存过期,我在其中使用expire_fragment("all_available_releases")使片段过期。我在更新、删除或添加条目的Controller的每个方法中都使用它。这是WEBrick的日志,尽管过期片段已在其中注册,但5行后过期片段被读取并使用,而这是不应该的。这个例子是在destroy调用之后。ProcessingbyReleasesCont

  7. ruby-on-rails - Rails 4.0 Strong Parameters 嵌套属性带有指向散列的键 - 2

    我在玩Rails4.xbeta并试图让嵌套属性与carrierwave一起工作。不确定我在做什么是正确的方向。四处搜索之后,最终查看了rails源代码和强大的参数,我发现了以下注释。#Notethatifyouuse+permit+inakeythatpointstoahash,#itwon'tallowallthehash.Youalsoneedtospecifywhich#attributesinsidethehashshouldbewhitelisted.https://github.com/rails/rails/blob/master/actionpack/lib/actio

  8. javascript - 4.0 更新后从 NodeJS 获取 "Segmentation fault: 11" - 2

    我刚刚重新安装了NodeJS。在重新安装之前,当我运行node-v时,我得到的版本号类似于“0.2.x”……这是一个奇怪的数字。因为我今天早上读到Node刚刚更新到版本4.x.x,所以我想我应该更新它。另外,我还有其他问题,所以我认为这可能是造成这种情况的原因。当我运行以下server.js时,我会打印出以下控制台。服务器.js...varexpress=require('express');varmongoose=require('mongoose');varbodyParser=require('body-parser');varmethodOverride=require('me

  9. javascript - URL 中的 HTML 和 CSS 导致 404 错误(用户代理 = Trident/4.0) - 2

    我在URL中收到一些带有代码片段(CSS、HTML和JavaScript)的404。据我所知,用户在他们的session期间在网站上的进展情况很好-它是一个电子商务网站,受影响的用户正在将东西放入他们的购物篮并检查OK等。在某些页面上,我看到404错误与看似成功的页面显示相邻。每次显示该页面(在该session中)时,我都会收到相同的404错误。记录的404错误示例:404;http://www.example.com/rrepeat:repeat-y;有问题的页面上有一个匹配实例(除了第一个“r”):我已经检查了包含的CSS文件,但没有匹配项(如果匹配,我想我会在包含CSS文件的所有

  10. javascript - ExtJS 4.0 的颜色字段 - 2

    您知道ExtJS4.x的ColorField实现吗?我尝试创建自己的(查看DateField源代码)但是选择器背景是透明的,我无法修复它:(这就是我创建颜色选择器的方式:Ext.create('Ext.picker.Color',{pickerField:me,ownerCt:me.ownerCt,renderTo:document.body,floating:true,hidden:true,focusOnShow:true,listeners:{scope:me,select:me.onSelect},keyNavConfig:{esc:function(){me.collapse

随机推荐