I met a task in which it is necessary to create an instance of an abstract class using reflection on C#. At the same time, it is forbidden to create heirs.
It is clear that it is forbidden to create such instances, but reflection helps to overcome this. The answers were advised to look in the source codes on the referencesource site, to look for something like an internal call to the constructor through reflection. A hint in the task: need to find a method in the framework that directly deals with calling the constructor and simulate its logic without unnecessary checks. But I can't find. I find how to create instance of abstract class, but without initializing variables.
How can create such an instance so that class variables with values, if they exist are also initialized?
CodePudding user response:
As mentioned in the comments, you can call the internal RuntimeTypeHandle.Allocate
method to create an instance of an abstact class. Afterwards you can actually call the constructor. Calling an abstract method will throw a System.BadImageFormatException
"Bad IL format." This allocate method only exists in the .Net Framework.
abstract class C
{
public string One;
public C()
{
One = "One";
}
public abstract void Abstract();
}
internal class Program
{
static void Main(string[] args)
{
var obj = (C)typeof(RuntimeTypeHandle).GetMethod("Allocate", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[] { typeof(C) });
typeof(C).GetConstructor(Type.EmptyTypes).Invoke(obj, new object[0]);
// outputs "One"
Console.WriteLine(obj.One);
// throws BadImageFormatException
obj.Abstract();
}
}
Another horrible unsafe option to somehow obtain an instance of an abstract type could be to rewrite an existing objects type information, see: https://github.com/IllidanS4/SharpUtils/blob/master/Unsafe/Chameleon.cs
CodePudding user response:
This is not possible, not even with reflection. You'll get a runtime error, as demonstrated in the comments. What is possible, is creating a proxy from an abstract class (e.g. using Castle.Core
). But that is still not creating an instance of an abstract class, but dynamically creates an implementation for the abstract members. And then creates an instance of that dynamically created implementation.