Is it possible to create an instance of an class without running ANY code from the class? (no ctor, no field initializations)
Asked Answered
R

2

6

I have created an engine that takes in 3rd party plugins (DLL's) that implement an interface.

Since I have no control over the code that gets plugged in, I want to be able to run 1 specific method (from the interface) from the correct class (GetTypes loop untill I find the interfaced class ).

Since anyone can create nice constructor code that executes on Activator.CreateInstance, I can solve that by using FormatterServices.GetUninitializedObject. But that does not help when code is being initialized on fields in the class.

public class myclass : myinterface {

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }

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

The problem with both ways (CreateInstance/GetUninitializedObject) is that the constructor of someotherclass will be run.

Before you start analyze my needs. This is only run in the initializing of the engine to get a set of standard values. If this get'er relies on other initialized values the "plugin" will be marked as failed as there is no valid value returned. If not marked as failed, later on the class will be loaded properly with Activator.CreateInstance().

So stick to this question: Does .Net support any way to create an 100% non-initialized class?

Update for the answers. I tested this before I posted my question.

For the answer that someotherclass wont run, I allready tested that and it is run if static.

public class myclass : myinterface {

    static Tutle test;

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

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

CreateInstance shows the messagebox. GetUninitializedObject does not.

public class myclass : myinterface {

    static Tutle test = new Tutle();

    public myclass () {
    }

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

CreateInstance shows the messagebox. GetUninitializedObject shows the messagebox.

Is there a way to get around static field intializers and ctors?

Revolutionist answered 3/1, 2013 at 9:41 Comment(2)
If you don't really want an object instance to be created, it sounds like you want a static property instead. Yes, it means you don't get to specify it in an interface... but you're already using reflection, so you can just check that all the types have the relevant property. Or if you know that the property value should always be a constant, perhaps require a custom attribute instead.Mightily
Whenever you have no control of the code that gets executed, you might consider executing that code in a separate AppDomain with limited permissions. This might be an alternative to creating an uninitialized object.Mylander
H
15

Simply:

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

That will not run the constructor / field initializers. At all. It will not run the constructor for someotherclass; name will be null.

It will, however, execute any static constructor that exists, if necessary under standard .NET rules.

HOWEVER! I should note that this method is not intended for ad-hoc usage; its primary intent is for use in serializers and remoting engines. There is a very good chance that the types will not work correctly if created in this way, if you have not subsequently taken steps to put them back into a valid state (which any serializer / remoting engine would be sure to do).

Herne answered 3/1, 2013 at 9:55 Comment(5)
Correct, the field initializer (public someotherclass name = new someotherclass(); in your example) will not be executed.Mylander
Check my update. GetUninitializedObject does run the code... Allready tested before posting. NM. Static was the issue. So no way to get around static then?Revolutionist
@Revolutionist I tested too ;p and no: it isn't (edit: this comment is now out of date since it is now marked static)Herne
Updated. Saw that my test was static. So the question still remains. And i assume the answer is No. does not work on static. Would be nice with interface constraints to say whats not allowed.Revolutionist
@Revolutionist re static: no, you can't prevent that if you are creating instances. But see my other answer for a way that does avoid that (attributes)Herne
H
6

As an alternative design consideration:

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

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }
}

Now you can access the feature without instantiation; just use:

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

with:

[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; }
}
Herne answered 3/1, 2013 at 10:3 Comment(2)
Thanks. I think I will add that. As the interface is published and set, I can do a precheck if the attribute is set, and use that before creating an instance. Backward compatibility.Revolutionist
I like this much better. GetUninitializedObject sounds very dangerous!Foin

© 2022 - 2024 — McMap. All rights reserved.