简体   繁体   English

尝试设置本机属性时,动态关键字抛出RunTimebinderException

[英]Dynamic keyword throwing RunTimebinderException when trying to set native property

I am using dynamic keyword to work with an outside assembly and it works fine as far as accessing it's methods and primitive type members are concerned. 我正在使用动态关键字来处理外部程序集,并且只要访问它的方法和原始类型成员就可以正常工作。 So for example my class dynamically loaded class looks like followig: 所以例如我的类动态加载类看起来像followig:

public class Student
{
    public bool IsGood { get; set; }
    public StudentType St { get; set; }
    public University University { get; set; }
}

I can dynamically load the object from assembly by doing something like: 我可以通过执行以下操作从程序集动态加载对象:

var assembly = Assembly.LoadFrom("//path");

Type type = assembly.GetType("TestFrameWork.Student");
var student = Activator.CreateInstance(type); 

It fails on following code: 它无法使用以下代码:

student.IsGood = true; student.IsGood = true;
student.St = TestFrameWork.StudentType.SomethingElse; student.St = TestFrameWork.StudentType.SomethingElse;

Student Type is an Enum from dynamically loaded assembly; 学生类型是动态加载程序集的枚举;

I can get the student object. 我可以得到学生的对象。 Now is the interesting part. 现在是有趣的部分。 I can call it's methods. 我可以称之为方法。 I can get all its properties. 我可以得到它的所有属性。 I can set it's primitive properties 我可以设置它的原始属性

So I can pretty much do student.IsGood = true; 所以我几乎可以做学生.IsGood = true; and it will set that property. 它将设置该属性。 That is equally true if I had other primitive properties of type int, float etc. 如果我有int,float等类型的其他原始属性,那也是如此。

BUT

When I try to set it to a property which is native to dynamically loaded assembly It fails with RuntimeBinderException 当我尝试将其设置为动态加载程序集的本机属性时,它失败并出现RuntimeBinderException

So for example, 所以,例如,

if I try to do student.University = new University() where University is a native type of loaded assembly. 如果我尝试做student.University = new University()其中大学是一个本地类型的装载组件。 It fails. 它失败。

here is the stack trace: 这是堆栈跟踪:

at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) System.RuntimeType.CreateInstaultDefaultCtor上的System.RuntimeType.CreateInstanceSlow(布尔值publicOnly,布尔值skipCheckThis,布尔fillCache,StackCrawlMark和stackMark)中的System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean noCheck,Boolean&canBeCached,RuntimeMethodHandleInternal&ctor,Boolean&bNeedSecurityCheck) (Boolean publicOnly,Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Reflection.Assembly.CreateInstance(String typeName) at TaskManagementFramework.PluginModule.CreateInstanceT in c:\\Dropbox\\CPTFramework_DynamicLoading\\TaskManagementFramework\\Plugin Loading\\PluginModule.cs:line 19 at TaskManagementFramework.PluginLifecycleManager.GetPluginInstance(String id, String parentXmlSectionDescription, Type expectedInterface, Boolean useSingleInstance, IPlugin& plugin) in c:\\Dro System.Activator.CreateInstance的System.Activator.CreateInstance(Type type,Boolean nonPublic)在System.Activator.CreateInstance的System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr,Binder binder,Object [] args,CultureInfo culture,Object [] activationAttributes,StackCrawlMark和stackMark)中的类型System,System.Reflection.Assembly.CreateInstance(String typeName,Boolean ignoreCase,BindingFlags bindingAttr,Binder binder,Object [] args,CultureInfo culture,对象[] activationAttributes)在System.Reflection.Assembly.CreateInstance(String typeName)at TaskManagementFramework.PluginModule.CreateInstanceT in c:\\ Dropbox \\ CPTFramework_DynamicLoading \\ TaskManagementFramework \\ Plugin Loading \\ PluginModule.cs:第19行在TaskManagementFramework.PluginLifecycleManager.GetPluginInstance(String) id,String parentXmlSectionDescription,Type expectedInterface,Boolean useSingleInstance,IPlugin&plugin)in c:\\ Dro pbox\\CPTFramework_DynamicLoading\\TaskManagementFramework\\Plugin Loading\\PluginLifecycleManager.cs:line 53 at TaskManagementFramework.PluginsXmlParser.ParsePlugins(XElement pluginsListElement, String parentXmlSectionDescription, PluginLifecycleManager pluginLifecycleManager, List`1& plugins) in c:\\Dropbox\\CPTFramework_DynamicLoading\\TaskManagementFramework\\XML Parsing\\PluginsXmlParser.cs:line 39 pbox \\ CPTFramework_DynamicLoading \\ TaskManagementFramework \\ Plugin Loading \\ PluginLifecycleManager.cs:第53行,位于c:\\ Dropbox \\ CPTFramework_DynamicLoading \\ TaskManagementFramework \\ XML Parsing \\ PluginsXmlParser中的TaskManagementFramework.PluginsXmlParser.ParsePlugins(XElement pluginsListElement,String parentXmlSectionDescription,PluginLifecycleManager pluginLifecycleManager,List`1&plugins) .cs:第39行

Any idea why? 知道为什么吗? I searched through internet nothing specifically addresses this isssue.. 我通过互联网搜索没有具体解决这个问题..

To summerize: .NET framework 4.0 absolutely does not support directly assigning the native types of dynamically loaded assembly. 总结一下:.NET framework 4.0绝对不支持直接分配动态加载程序集的本机类型。

Which means that we will have to do something that has been suggested in the answer above which is: 这意味着我们必须做一些上面答案中建议的事情:

Type type = assembly.GetType("TestFrameWork.Student");
 type.GetProperty("University").SetValue(student, new University(), null);

If you are loading the entire assembly at runtime which you probably are you will not have University type ar compile time as well. 如果您在运行时加载整个程序集,那么您可能也没有大学类型的编译时间。 In that case your solution is 在那种情况下,你的解决方案是

type2 =  assembly.GetType("TestFrameWork.University");
type.GetProperty("University").SetValue(student, Activator.CreateInstance(type2`enter code here`), null);

Hopefully this helps. 希望这会有所帮助。

But I think this is a bug in .Net 4.0. 但我认为这是.Net 4.0中的一个错误。 I might be wrong though 我可能错了

I believe the correct way to do this sort of thing is like this 我相信做这种事的正确方法是这样的

class Program
{
    static void Main(string[] args)
    {
        object d = new Person();
        d.GetType().GetField("Parent").SetValue(d,new Person("Test"));
        Console.WriteLine(((Person)d).Parent.name);
        Console.Read();
    }
}

public class Person{
    public String name = "";
    public Person Parent;

    public Person()
    {
    }
    public Person(String s)
    {
        name = s;
    }
}

Cast the University into an object and set the value using reflection. 将大学转换为对象并使用反射设置值。 Here is an example with simple code, just replace Person with whatever university is : 这是一个简单代码的例子,只需用任何大学代替Person:

If this does not work, it probably means that university inside of your native code cannot be parsed into university because they are seen as two different types. 如果这不起作用,则可能意味着您的本机代码中的大学无法解析为大学,因为它们被视为两种不同的类型。 So create an instance of the university that object is using and set values to that. 因此,创建一个对象正在使用的大学实例,并为其设置值。 Once you've done that set that instance you created. 完成后,设置您创建的实例。

like such (its psuedocode btw) : 像这样(它的伪代码顺便说一句):

var assembly = Assembly.LoadFrom("//path");

Type type = assembly.GetType("TestFrameWork.University");
var Uni = Activator.CreateInstance(type); 
type = assembly.GetType("TestFrameWork.Student");
var student = Activator.CreateInstance(type); 
student.University = Uni;

Edit: The enum The enum is a little bit more tricky Here is something I definitely think will help: 编辑:枚举枚举有点棘手这是我绝对认为会有所帮助的东西:

 class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();

        Type t = p.Enuminator.GetType();
        dynamic e = Activator.CreateInstance(t);
        FieldInfo [] FieldArray = t.GetFields();

        p.GetType().GetField("Enuminator").SetValue(p, FieldArray[3].GetValue(e));

        Console.WriteLine(p.Enuminator);
        Console.Read();
    }
}

public class Person{
    public String name = "";
    public Person Parent;
    public Enumtest Enuminator;

    public Person()
    {
    }
    public Person(String s)
    {
        name = s;
    }
}

public enum Enumtest
{
    chicken,
    monkey,
    frog
}

It definitely is ugly; 这绝对是丑陋的; however you should be able to pull this off as long as you know the structure you are trying to import ahead of time. 但是,只要您知道要提前导入的结构,就应该能够将其关闭。 Also you can change Dynamic type with Object type. 您还可以使用对象类型更改动态类型。 I only did that because I trying get it right. 我只是这样做,因为我尝试做对了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试使用动态类型时RuntimeBinderException - RuntimeBinderException when trying to use dynamic type 尝试实例化动态类型的数组时发生RuntimeBinderException(后期绑定) - RuntimeBinderException when trying to instantiate an array of a dynamic type (late-binding) 动态属性分配引发RuntimeBinderException - Dynamic Property Assignment Throws RuntimeBinderException 动态清单 <T> 。添加引发RuntimeBinderException - dynamic List<T>.Add throwing RuntimeBinderException 使用动态对象时的RuntimeBinderException - RuntimeBinderException when using dynamic object 从不同库中方法的“ dynamic”结果读取属性时出现RuntimeBinderException - RuntimeBinderException when reading property from `dynamic` result from method in different library 在私有类型上动态抛出Microsoft.CSharp.RuntimeBinder.RuntimeBinderException - Dynamic throwing Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on private types 在视图中访问动态匿名类型时的RuntimeBinderException - RuntimeBinderException when accessing dynamic anonymous type in view 尝试从api解析json时出现RuntimeBinderException - RuntimeBinderException when trying to parse json from api 为什么“动态”ExpandoObject 即使包含属性定义也会抛出 RuntimeBinderException? - Why 'dynamic' ExpandoObject throws RuntimeBinderException even if it contains the definition for a property?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM