1

基本上我想要的介于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,但我还没有找到足够的信息来决定。

4

2 回答 2

0

我感谢对此的帮助和指导,但是对于我的最终解决方案,我决定跳出框框思考一下。

由于这是针对具有内部可配置和外部可覆盖设置的插件系统,因此即使插件未完全初始化,我也希望设置可以访问。

我的解决方案是在插件类型上创建一个属性,该属性是指向另一个包含设置的类型的指针。就像我说的,在盒子外面。

这使我可以在开始初始化插件之前查看属性和定义的设置类,创建设置类的实例并填充它。(这还有一个好处是能够在完全不启用插件的情况下修改插件设置)

然后在实例创建代码的插件包装器中,我检测到插件上是否有一个构造函数接受相同的类型并使用它,否则它使用默认值。

于 2019-12-09T16:12:46.677 回答
0

据我所知,没有与C++ 的位置 new相结合的类似物FormatterServices.GetUninitializedObject可能会解决您的问题。

但是我相信您正在尝试做的是朝着错误的方向迈出的一步-尝试与构造函数不变量作斗争/对未初始化的对象进行工作通常是一个坏主意

除非这是一些已经活跃且(相对)广泛使用的插件系统,并且您别无选择,否则我建议您使用更标准且与语言/平台无关的方法之一重新设计它:

  1. 将所有参数作为一些Dictionary/传递给构造函数dynamic
  2. 或者对一些IPluginFactory.Create.
  3. 或者有一个Initialize方法接受相同的Dictionary/dynamic并在插件构建后对其进行初始化。

就个人而言,我会选择构造函数接受Dictionary/ dynamic

于 2019-11-23T14:35:31.597 回答