1

我想允许继承,但禁止直接构造任何继承的类。相反,我想强制使用自定义方法New()

目标是确保继承类的每个实例都是其自身的透明代理。

在这种情况下,不可能创建构造函数privateinternal. 否则,您不能再从程序集之外的类继承。

有什么优雅的方法可以解决这个问题吗?我目前的解决方案:

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.");
        }
    }
}
4

1 回答 1

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.");
    }
}
于 2019-04-01T16:04:56.493 回答