Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尝试设置本机属性时动态关键字引发RunTimebinderException_C#_.net_C# 4.0_Dynamic_.net 4.0 - Fatal编程技术网

C# 尝试设置本机属性时动态关键字引发RunTimebinderException

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 =

我使用dynamic关键字处理外部程序集,就访问其方法和基本类型成员而言,它工作得很好。例如,我的类动态加载的类如下所示:

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=true
student.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);