C# 获取类型的实例,而不调用构造函数,但仍初始化字段/属性;
基本上,我想要的是介于C# 获取类型的实例,而不调用构造函数,但仍初始化字段/属性;,c#,object-initialization,C#,Object Initialization,基本上,我想要的是介于FormatterServices.GetUninitializedObject()和Activator.CreateInstance()之间的内容 这是一个插件类型的系统,所以类型是可变的,但我不认为这是一个问题,因为上面两个处理变量类型都很好 基本上,我想创建插件类的实例,用定义的值初始化所有字段和属性,但在父应用程序看到是否有任何要注入的配置设置之前,不要调用构造函数 IInputDeviceEnumerator newEnum = (IInputDeviceEnum
FormatterServices.GetUninitializedObject()
和Activator.CreateInstance()
之间的内容
这是一个插件类型的系统,所以类型是可变的,但我不认为这是一个问题,因为上面两个处理变量类型都很好
基本上,我想创建插件类的实例,用定义的值初始化所有字段和属性,但在父应用程序看到是否有任何要注入的配置设置之前,不要调用构造函数
IInputDeviceEnumerator newEnum = (IInputDeviceEnumerator)FormatterServices.GetUninitializedObject(type);
if (newEnum is IIMConfigurable typeSettings)
{
string pluginDirectory = Path.GetDirectoryName(new System.Uri(typeSettings.GetType().Assembly.CodeBase).AbsolutePath);
string pluginConfigPath = Path.Combine(pluginDirectory, "settings.json");
if (File.Exists(pluginConfigPath))
{
try
{
JsonConvert.PopulateObject(File.ReadAllText(pluginConfigPath), typeSettings.config);
}
catch { }
}
SharedProperties.Settings.pluginSettings.settingsGroups.Add(typeSettings.config);
}
var constructor = type.GetConstructor(Type.EmptyTypes);
constructor.Invoke(newEnum, null);
我感觉答案就在
PopulateObjectMembers
的某个地方,但我还没有找到足够的信息来决定。据我所知,没有类似于FormatterServices的方法。GetUninitializedObject
可能解决了您的问题
但我认为你试图做的是朝着错误的方向迈出的一步-试图对抗构造函数不变量/在未初始化的对象上工作通常是个坏主意
除非这是一个已经活跃且(相对)广泛使用的插件系统,您别无选择,否则我建议您使用一种更标准且与语言/平台无关的方法重新设计它:
字典
/动态
传递给构造函数IPluginFactory执行相同的操作。创建
Initialize
方法,该方法接受相同的字典
/动态
,并在构建插件后初始化插件就我个人而言,我会选择构造函数接受
字典
/动态
,据我所知,没有类似的东西与FormatterServices相结合。GetUninitializedObject
可能会解决您的问题
但我认为你试图做的是朝着错误的方向迈出的一步-试图对抗构造函数不变量/在未初始化的对象上工作通常是个坏主意
除非这是一个已经活跃且(相对)广泛使用的插件系统,您别无选择,否则我建议您使用一种更标准且与语言/平台无关的方法重新设计它:
字典
/动态
传递给构造函数IPluginFactory执行相同的操作。创建
Initialize
方法,该方法接受相同的字典
/动态
,并在构建插件后初始化插件就我个人而言,我会选择使用
字典
/动态
我感谢您在这方面的帮助和指导,但对于我的最终解决方案,我决定跳出框框思考一下
因为这是一个插件系统,既有内部可配置的设置,也有外部可覆盖的设置,所以我希望即使插件没有完全初始化,也能访问这些设置
我的解决方案是在插件类型上创建一个属性,该属性是指向另一个包含设置的类型的指针。就像我说的,在盒子外面
这允许我在初始化插件之前查看属性和定义的设置类,创建设置类的实例并填充所有内容。(这还有一个好处,就是可以在不启用插件的情况下修改插件设置)
然后,在实例创建代码中的插件包装中,我检测到插件上是否存在接受相同类型的构造函数,并使用该构造函数,否则它将使用默认值。我感谢在这方面提供的帮助和指导,但对于我的最终解决方案,我决定跳出框框思考一下 因为这是一个插件系统,既有内部可配置的设置,也有外部可覆盖的设置,所以我希望即使插件没有完全初始化,也能访问这些设置 我的解决方案是在插件类型上创建一个属性,该属性是指向另一个包含设置的类型的指针。就像我说的,在盒子外面 这允许我在初始化插件之前查看属性和定义的设置类,创建设置类的实例并填充所有内容。(这还有一个好处,就是可以在不启用插件的情况下修改插件设置)
然后,在实例创建代码中的插件包装中,我检测到插件上是否存在接受相同类型的构造函数,并使用该构造函数,否则将使用默认值。您的代码有什么问题?@PavelAnikhouski这不会初始化字段或属性,它们都是null或默认值。如果类具有
boolmyval{get;set;}=true代码>我想让上面的代码看到指定的值。(粗略简化的例子,我的类型默认值有点复杂)我认为,期望一个对象在不调用构造函数的情况下正常运行是非常脆弱的。为什么要提前设置属性,而不调用构造函数?我要么早点构造完整对象,要么推迟设置属性,直到您知道您需要一个实例。@JonSkeet,原因如下。插件的执行通常是由它们的构造函数启动的,我不希望它们在主应用程序加载相关信息之前启动。为此,我可以在接口中添加一个init()
方法,但希望避免这种情况。我真的不需要对象正常“运行”,只需要在不久之后调用构造函数时填充字段。@Wobbles:添加初始化方法几乎肯定是一种更好的方法。在设置字段等之后调用构造函数的想法真的很流行