I want to allow inheritance, but forbid the direct construction of any of the inherited classes. Instead, I want to force the usage of the custom method New()
.
The goal is to make sure that every instance of inherited classes is a transparent proxy of itself.
In this case, it's not possible to make the constructor private
or internal
. Otherwise, you can't inherit from the class anymore outside of the assembly.
Is there any elegant way to solve that? My current solution:
public abstract class Class<This> : MarshalByRefObject where This : Class<This>
{
private static bool ShouldThrowOnConstruction = true;
private static readonly object Lock = new object();
public static This New()
{
lock (Lock)
{
ShouldThrowOnConstruction = false;
var instance = (This)new ClassProxy<This>().GetTransparentProxy();
ShouldThrowOnConstruction = true;
}
return instance;
}
protected Class()
{
if (ShouldThrowOnConstruction)
{
throw new InvalidOperationException("Direct use of the constructor is forbidden. Use New() instead.");
}
}
}
Why not use a static factory function instead of a constructor?
e.g.
That's extremely difficult to misuse, and doesn't have the same race condition problems that you required the thread locking for.
I suppose this means that all subclasses would also need to make their default constructor private. Is that outside your control?
Edit:
In the case you want to guarantee it can't be called, make the constructor throw an exception
throw new InvalidOperationException("Direct use of the constructor is forbidden. Use Build() instead.");
, and yourGetTransparentProxy
method shouldn't callnew
to construct the object but instead useFormatterServices.GetUninitializedObject()
to bypass the constructor. That should allow the instance to be created, but it has a bit of a code smell.Something like this: