我想允许继承,但禁止直接构造任何继承的类。相反,我想强制使用自定义方法New()
。
目标是确保继承的类的每个实例都是其自身的透明代理。
在这种情况下,不可能使构造函数为private
或internal
。否则,您将无法再从程序集外部继承该类。
有什么优雅的方法可以解决这个问题吗?我当前的解决方案:
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.");
}
}
}
答案 0 :(得分:4)
为什么不使用静态工厂函数代替构造函数?
例如
public abstract class Class<This> : MarshalByRefObject where This : Class<This>
{
public static Class<This> Build()
{
var instance = (This)new ClassProxy<This>().GetTransparentProxy();
}
protected Class()
{
}
}
这是非常难于滥用的,并且没有您需要线程锁定的竞争条件问题。
我想这意味着所有子类也需要将其默认构造函数设为私有。那是您无法控制的吗?
编辑:
如果要保证无法调用它,请使构造函数抛出异常throw new InvalidOperationException("Direct use of the constructor is forbidden. Use Build() instead.");
,而您的GetTransparentProxy
方法不应调用new
来构造对象但是使用FormatterServices.GetUninitializedObject()
绕过构造函数。那应该允许创建实例,但是有点代码味道。
类似这样的东西:
public abstract class Class<This> : MarshalByRefObject where This : Class<This>
{
public static Class<This> Build()
{
// Ensure GetTransparentProxy() calls FormatterServices.GetUninitializedObject() to create the object, rather than calling `new`
var instance = (This)new ClassProxy<This>().GetTransparentProxy();
}
protected Class()
{
throw new InvalidOperationException("Direct use of the constructor is forbidden. Use Build() instead.");
}
}