C# 尝试设置本机属性时动态关键字引发RunTimebinderException
我使用dynamic关键字处理外部程序集,就访问其方法和基本类型成员而言,它工作得很好。例如,我的类动态加载的类如下所示:C# 尝试设置本机属性时动态关键字引发RunTimebinderException,c#,.net,c#-4.0,dynamic,.net-4.0,C#,.net,C# 4.0,Dynamic,.net 4.0,我使用dynamic关键字处理外部程序集,就访问其方法和基本类型成员而言,它工作得很好。例如,我的类动态加载的类如下所示: public class Student { public bool IsGood { get; set; } public StudentType St { get; set; } public University University { get; set; } } 我可以通过执行以下操作从程序集中动态加载对象: var assembly =
public class Student
{
public bool IsGood { get; set; }
public StudentType St { get; set; }
public University University { get; set; }
}
我可以通过执行以下操作从程序集中动态加载对象:
var assembly = Assembly.LoadFrom("//path");
Type type = assembly.GetType("TestFrameWork.Student");
var student = Activator.CreateInstance(type);
它在以下代码中失败:
student.IsGood=truestudent.St=TestFrameWork.StudentType.SomethingElse 学生类型是来自动态加载程序集的枚举 我可以得到学生对象。现在是有趣的部分。我可以称之为方法。我可以得到它的所有属性。我可以设置它的基本属性 所以我几乎可以做学生了;它将设置该属性。如果我有int、float等类型的其他基本属性,这同样正确 但是 当我尝试将其设置为动态加载程序集的本机属性时,它会因RuntimeBinderException而失败 那么比如说, 如果我尝试执行student.University=new University(),其中University是加载程序集的本机类型。它失败了 以下是堆栈跟踪: 在System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,布尔值 publicOnly、Boolean noCheck、Boolean&canBeCached、, RuntimeMethodHandleInternal&ctor、Boolean&bNeedSecurityCheck)位于 System.RuntimeType.CreateInstanceSlow(布尔publicOnly,布尔型 skipCheckThis、布尔填充缓存、堆栈爬网标记和堆栈标记)位于 System.RuntimeType.CreateInstanceDefaultCtor(仅限布尔值), 布尔skipCheckThis、布尔填充缓存、堆栈爬网标记和堆栈标记)
位于的System.Activator.CreateInstance(类型,布尔非公共) System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr,Binder 活页夹,对象[]参数,文化信息文化,对象[] 激活属性、堆栈爬网标记和堆栈标记)位于 System.Activator.CreateInstance(类型类型,BindingFlags bindingAttr, 活页夹活页夹,对象[]参数,文化信息文化,对象[] 激活(属性)在 System.Reflection.Assembly.CreateInstance(字符串类型名,布尔值 ignoreCase,BindingFlags bindingAttr,Binder Binder,对象[]参数, CultureInfo区域性,对象[]激活属性)位于 位于的System.Reflection.Assembly.CreateInstance(字符串typeName) 中的TaskManagementFramework.PluginModule.CreateInstanceT c:\Dropbox\CPTFramew\U DynamicLoading\TaskManagementFramework\Plugin 正在加载\PluginModule.cs:第19行 TaskManagementFramework.PluginLifecycleManager.GetPluginInstance(字符串 id,字符串parentXmlSectionDescription,类型expectedInterface, Boolean useSingleInstance、IPlugin和plugin)中的 c:\Dropbox\CPTFramew\U DynamicLoading\TaskManagementFramework\Plugin 正在加载\PluginLifecycleManager.cs:第53行 TaskManagementFramework.PluginsXmlParser.ParsePlugins(XElement pluginsListElement,字符串parentXmlSectionDescription, PluginLifecycleManager PluginLifecycleManager,在中列出'1和plugins c:\Dropbox\CPTFramew\U DynamicLoading\TaskManagementFramework\XML 解析\PluginsXmlParser.cs:第39行
知道为什么吗?我在互联网上搜索,没有任何东西专门针对这一问题。我相信做这类事情的正确方法是这样的
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;
}
}
将大学投射到一个对象中,并使用反射设置值。下面是一个简单代码的示例,只需将Person替换为任何大学即可:
如果这不起作用,可能意味着本机代码中的university无法解析为university,因为它们被视为两种不同的类型。所以,创建一个对象正在使用的大学的实例,并为其设置值。完成此操作后,设置创建的实例
类似的(其psuedocode btw):
编辑:枚举
枚举有点棘手
以下是我认为肯定会有所帮助的:
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
}
这绝对是丑陋的;但是,只要您提前知道要导入的结构,就应该能够实现这一点。还可以使用对象类型更改动态类型。我之所以这样做,是因为我试图正确地进行操作。对于Summize:.NET framework 4.0绝对不支持直接分配动态加载程序集的本机类型 这意味着我们将不得不做上面答案中建议的事情,即:
Type type = assembly.GetType("TestFrameWork.Student");
type.GetProperty("University").SetValue(student, new University(), null);
如果您在运行时加载整个程序集(您可能正在加载),那么您也不会有大学类型的ar编译时。在这种情况下,您的解决方案是
type2 = assembly.GetType("TestFrameWork.University");
type.GetProperty("University").SetValue(student, Activator.CreateInstance(type2`enter code here`), null);
希望这能有所帮助
但我认为这是.NET4.0中的一个bug。虽然提供stacktrace,但我可能是错的。我在问题中添加了stacktrace。学生中的大学类型似乎与您尝试分配的类型不同。我希望出现无效的强制转换异常,但该信息可以作为内部异常隐藏或可用。您可能还希望提供该问题的小型自包含副本,供其他人调试。@leppie:我的代码非常小。我刚刚编辑了这个问题,并添加了失败的代码。如果你需要更多的信息,请告诉我。所以试着按照你的建议去做。type.GetField(“Fieldname”)不断返回Null。我是否应该使用GetProperty而不是GetField?是否尝试了第二个选项?方法1本身可以工作。我所要做的就是用GetProperty替换GetField:
type.GetProperty(“University”).SetValue(student,Activator.CreateInstance(type4),null)代码>如您所见,我在setvalue中用一个动态对象替换了具体对象,它似乎仍然有效。但当我用enum尝试同样的方法时,它失败了。但我将为此提出一个新问题。非常感谢。
type2 = assembly.GetType("TestFrameWork.University");
type.GetProperty("University").SetValue(student, Activator.CreateInstance(type2`enter code here`), null);