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:添加初始化方法几乎肯定是一种更好的方法。在设置字段等之后调用构造函数的想法真的很流行