Dynamic keyword RunTimebinderException thrown when trying to set its own property

I use a dynamic keyword to work with an external assembly, and it works great with access to its methods and elements of a primitive type. So, for example, a class of a dynamically loaded class looks like this:

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

I can dynamically load an object from an assembly by doing something like:

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

The following code could not be executed:

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

Student type is an enumeration from a dynamically loaded assembly;

I can get the student object. Now for the interesting part. I can call it methods. I can get all its properties. I can set its primitive properties

So I can pretty much do student.IsGood = true; and he will set this property. The same is true if I had other primitive properties like int, float, etc.

BUT

When I try to set it to a property that is native to a dynamically loaded assembly, it does not work with a RuntimeBinderException

So for example

if I try to make student.University = new University (), where University is the native type of the loaded assembly. It fails.

Here is the stack trace:

in System.RuntimeTypeHandle.CreateInstance (RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean & canBeCached, RuntimeMethodHandleInternal & ctor, Boolean & bNeedSecurityCheck) in System.RuntimeType.CreateInstanceSlow (Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark & ​​stackMark) when System .RuntimeType.CreateInstanceDefaultCtor (Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark & ​​stackMark)
in System.Activator.CreateInstance (Type of type, Boolean nonPublic) in System.RuntimeType.CreateInstanceImpl (BindingFlags bindingAttr, Binder binder, Object [] args, CultureInfo culture, Object [] activAttributes, StackCrawlMark & ​​stackMark) at System.Activator (stack. Type type, BindingFlags bindingAttr, Binder binder, Object [] args, CultureInfo culture, Object [] activAttributes) in System.Reflection.Assembly.CreateInstance (String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binding binder, Object [] args, CultureInfo , Object [] activationAttributes) in System.Reflection.Assembly.CreateInstance (String typeName) in TaskManagementFramework.PluginModule.CreateInstanceT in C: \ Dropbox \ CPTFramework_DynamicLoading \ TaskManagementFramework \ Plugin Loading \ PluginModuleManuleLanguinGumentulePlugin.luginMluguleLanguinGuinMan String id, String parentXmlSe ctionDescription, Type expectedInterface, Boolean useSingleInstance, IPlugin & plugin) in C: \ Dropbox \ CPTFramework_DynamicLoading \ TaskManagementFramework \ Plugin Download \ PluginLifecycleManager.cs: line 53 in TaskManagementFrameworkLmentMlementleMlementleMlementleMlementleMlementleMlementLmentMLElLEMLEMLEMlElMlElMlElleMlleLmentLaLleMleLentLentLentLentemLentLentemLentLaLleMleLentLentLentMentemLentLentmeLentmeLentemLentLaMleLemLentLentLentMentIFLentLentermain & plugins) in C: \ Dropbox \ CPTFramework_DynamicLoading \ TaskManagementFramework \ XML Parsing \ PluginsXmlParser.cs: line 39

Any idea why? I searched through the Internet for nothing specifically addressing this isssue ..

+4
source share
2 answers

To summerize: .NET framework 4.0 absolutely does not support the direct assignment of native types of dynamically loaded assemblies.

This means that we will need to do something that was suggested in the answer above:

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

If you load the entire assembly at runtime, which probably you probably won't have a university type compilation time. In this case, your decision

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

Hope this helps.

But I think this is a bug in .Net 4.0. I may be wrong, but

+2
source

I believe the correct way to do things like this is:

 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; } } 

Pass the university to the object and set the value using reflection. Here is a simple code example, just replace Person with any university:

If this does not work, it probably means that the university inside your own code cannot be analyzed at the university, because they are considered as two different types. So, create an instance of the university that uses this object, and set values ​​for it. After you have made this set, the instance you created.

as 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: enumeration Enumeration is a little more complicated Here is what 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 is definitely ugly; however, you should be able to do this if you know the structure that you are trying to import in advance. You can also change the dynamic type with the type of the object. I just did it because I'm trying to figure it out.

+1
source

Source: https://habr.com/ru/post/1498623/


All Articles