6

我创建了一个引擎,它接受实现接口的 3rd 方插件 (DLL)。

由于我无法控制插入的代码,因此我希望能够从正确的类(GetTypes 循环直到找到接口类)运行 1 个特定方法(从接口)。

由于任何人都可以创建在Activator.CreateInstance上执行的漂亮的构造函数代码,因此我可以使用FormatterServices.GetUninitializedObject来解决这个问题。但这在类中的字段上初始化代码时无济于事。

public class myclass : myinterface {

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }

  //I only want this run.
  public string MyProperty{
    get {
      return "ANiceConstString";
    }
  }
}

两种方式(CreateInstance/ GetUninitializedObject)的问题在于将运行某个其他类的构造函数。

在你开始分析我的需求之前。这仅在引擎初始化时运行以获得一组标准值。如果此 get'er 依赖于其他初始化值,则“插件”将被标记为失败,因为没有返回有效值。如果未标记为失败,稍后将使用Activator.CreateInstance()正确加载该类。

所以坚持这个问题:.Net 是否支持任何方式来创建 100% 未初始化的类?

更新答案。在发布我的问题之前,我对此进行了测试。

对于某个其他类无法运行的答案,我已经对其进行了测试,如果是静态的,它就会运行。

public class myclass : myinterface {

    static Tutle test;

    public myclass () {
         test = new Tutle();
    }

    public class Tutle {
        public Tutle() {
            MessageBox.Show("RUN!");
        }
    }
}

CreateInstance 显示消息框。GetUninitializedObject 没有。

public class myclass : myinterface {

    static Tutle test = new Tutle();

    public myclass () {
    }

    public class Tutle {
        public Tutle() {
            MessageBox.Show("RUN!");
        }
    }
}

CreateInstance 显示消息框。GetUninitializedObject 显示消息框。

有没有办法绕过静态字段初始化器和 ctors?

4

2 回答 2

15

简单地:

var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass));

将不会运行构造函数/字段初始化程序。完全没有。它不会someotherclass为;运行构造函数。namenull

但是,如果有必要,它会在标准 .NET 规则下执行任何存在的静态构造函数。

然而!我应该注意,此方法不适用于临时使用;它的主要目的是用于序列化程序和远程引擎。如果以这种方式创建这些类型很有可能无法正常工作,如果您随后没有采取措施将它们恢复到有效状态(任何序列化程序/远程处理引擎肯定会这样做)。

于 2013-01-03T09:55:01.400 回答
5

作为替代设计考虑:

[SomeFeature("ANiceConstString")]
public class myclass : myinterface {

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }
}

现在您无需实例化即可访问该功能;只需使用:

var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
    type, typeof(SomeFeatureAttribute));
string whatever = attrib == null ? null : attrib.Name;

和:

[AttributeUsage(
    AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public sealed class SomeFeatureAttribute : Attribute
{
    private readonly string name;
    public string Name { get { return name; } }
    public SomeFeatureAttribute(string name) { this.name = name; }
}
于 2013-01-03T10:03:46.203 回答