如何确保只有A类可以创建A.B实例?

时间:2016-07-29 03:24:44

标签: c#

我有一个发布请求对象的代理类,并希望将它们传递给它,并将一些属性更改为合理的值。问题是所述代理的消费者必须从不更改该对象的几个只读属性,也不能创建不同的请求实例来欺骗该只读保护,或者代理将中断并抛出异常。如果代理的任何类保存尝试创建请求对象,我想找到一种方法使编译失败。

我认为密封请求对象的实例化所以它只能从代理本身内部完成是一个巧妙的想法加上只读属性,所以请求处理器永远不会欺骗系统,但我很难这样做。我尝试了一个带有私有构造函数的子类,如下所示:

public class PermissionsRequestBroker {
    public PermissionsRequest Test() {
        return new PermissionsRequest();
    }

    private class PermissionsRequest {
        private PermissionsRequest() {

        }
    }
}

但它失败了,因为代理无法创建请求对象。

我尝试了类似的方法,但是使用了这样的界面:

public class PermissionsRequestBroker {
    public IPermissionsRequest Test() {
        return new PermissionsRequest();
    }

    public interface IPermissionsRequest {

    }

    private class PermissionsRequest : IPermissionsRequest {
        public PermissionsRequest() {

        }
    }
}

但是请求处理器可以实现IPermissionsRequest并以这种方式欺骗系统。当然,我可以实现运行时检查,因此返回的对象仍然是代理的PermissionRequest对象,但仍然是运行时检查,并将抛出异常。

我所有的例外情况,但我觉得必须有一些方法在编译时强制执行该合同而不安装任何类型的IDE扩展或NuGet包。

2 个答案:

答案 0 :(得分:1)

PermissionsRequestBrokerPermissionsRequest放在一个单独的程序集中,并将PermissionsRequest标记为internal而不是public。然后,如果您需要使用者能够保留PermissionsRequest对象的实例,请将其包装在另一个public的类中。

如下所示:

public class PermissionsRequestBroker {
   public PermissionsRequestWrapper Test() {
      return new PermissionsRequestWrapper( new PermissionsRequest() );
   }
}

internal class PermissionsRequest {
   internal PermissionsRequest() {

   }
}

// Use 'sealed' to prevent others from inheriting from this class
public sealed class PermissionsRequestWrapper {
   private PermissionsRequest _permissionsRequest;

   internal PermissionsRequestWrapper(PermissionsRequest permissionsRequest) {
      _permissionsRequest = permissionsRequest;
   }

   /* etc... */
}

答案 1 :(得分:1)

我知道这已经回答了,但我很好奇......为什么这不起作用?

编辑:有一个大脑冻结时刻,下面的代码无效,请看之后的编辑。

public class PermissionsRequestBroker {
    public PermissionsRequest Test() {
        return new PermissionsRequest();
    }

    public sealed class PermissionsRequest {
        private PermissionsRequest() {

        }
    }
}

基本上将内部类公开并密封,但只将其构造函数设为私有?

修改

如果我们反过来,那么实施起来会更简单吗?当然,经纪人的静态是可选的。

public class PermissionsRequest
{
    private PermissionsRequest()
    { }

    public sealed class Broker
    {
        public static PermissionsRequest CreatePermissionsRequest()
        {
            return new PermissionsRequest();
        }

        public PermissionsRequest CreatePermissionsRequest_Instance()
        {
            return new PermissionsRequest();
        }
    }
}

public class UserClass
{
    public void Blah()
    {
        var permissionsRequest = PermissionsRequest.Broker.CreatePermissionsRequest();

        var broker = new PermissionsRequest.Broker();

        var permRequest = broker.CreatePermissionsRequest_Instance();
    }
}