是否可以在不运行类中的任何代码的情况下创建类的实例? (没有ctor,没有字段初始化)

时间:2013-01-03 09:41:51

标签: c# class initialization createinstance

我创建了一个引入实现接口的第三方插件(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)的问题是将运行 someotherclass 的构造函数。

在开始分析我的需求之前。这仅在初始化引擎时运行以获得一组标准值。如果此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?

2 个答案:

答案 0 :(得分:15)

简单地:

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

不会运行构造函数/字段初始值设定项。完全没有。它不会运行someotherclass的构造函数; name将为null

但是,如果有必要,它将执行任何存在的静态构造函数。

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

答案 1 :(得分: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; }
}