我使用动态关键字来处理外部程序集,并且只要访问它的方法和原始类型成员就可以正常工作。因此,例如我的类动态加载类看起来像followig:
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;
学生类型是来自动态加载程序集的枚举;
我可以获得学生对象。现在是有趣的部分。我可以称之为方法。我可以得到它的所有属性。我可以设置它的原始属性
所以我几乎可以做学生.IsGood = true;它将设置该属性。如果我有int,float等类型的其他原始属性,那也是如此。
BUT
当我尝试将其设置为动态加载程序集的本机属性时失败并出现RuntimeBinderException
例如,
如果我尝试做学生.University = new University()其中大学是一种本地类型的装配。它失败。
这是堆栈跟踪:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type,Boolean publicOnly,Boolean noCheck,Boolean& canBeCached, RuntimeMethodHandleInternal&安培; ctor,布尔& 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.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 \插件 Loading \ PluginModule.cs:第19行 TaskManagementFramework.PluginLifecycleManager.GetPluginInstance(字符串 id,String parentXmlSectionDescription,Type expectedInterface, Boolean useSingleInstance,IPlugin&插件) C:\ Dropbox的\ CPTFramework_DynamicLoading \ TaskManagementFramework \插件 Loading \ PluginLifecycleManager.cs:第53行 TaskManagementFramework.PluginsXmlParser.ParsePlugins(的XElement pluginsListElement,String parentXmlSectionDescription, PluginLifecycleManager pluginLifecycleManager,List`1&插件) C:\ Dropbox的\ CPTFramework_DynamicLoading \ TaskManagementFramework \ XML Parsing \ PluginsXmlParser.cs:第39行
知道为什么吗?我通过互联网搜索没有具体解决这个问题..
答案 0 :(得分:2)
总结一下:.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);
希望这有帮助。
但我认为这是.Net 4.0中的一个错误。我可能错了
答案 1 :(得分:1)
我相信做这种事的正确方法就是这样
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替换为任何大学:
如果这不起作用,可能意味着您的本机代码中的大学无法解析为大学,因为它们被视为两种不同的类型。因此,创建一个对象正在使用的大学实例,并为其设置值。完成后,设置您创建的实例。
像这样(它的伪代码顺便说一下):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;
编辑:枚举 枚举有点棘手 以下是我认为有用的内容:
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
}
绝对是丑陋的;但是,只要您知道要提前导入的结构,就应该能够将其关闭。您还可以使用对象类型更改动态类型。我只是这样做,因为我试着做对了。