2016-07-29 101 views
0

我有一个代理类发出请求对象,并期望它们被传回给它,并将一些属性更改为明智的值。问题是,的消费者表示,券商必须从未更改该对象的一对夫妇的只读属性,也可以创建不同的请求实例作弊是只读保护或经纪人将打破,并抛出一个异常。如果代理的任何类保存尝试创建请求对象,我想找到一种方法来使编译失败。如何确保只有一个类可以创建一个A.B实例?

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

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包。

+0

什么问题是你想解决? “欺骗”是什么意思,你不相信你的图书馆的用户?你看过'sealed'关键字吗? – Aron

+0

为什么你在第一个案例中使构造函数保密?在班级本身是私人的时候不会公开,而不是公开解决你的问题? – Madhusudhan

+0

@Aron PermissionRequest实例具有绝对不能更改的RequestId属性。IE:如果经纪人向您发送一个带有Id:0的请求,那么经纪人会希望您使用同一个ID回复,否则经纪人本身会中断并回复不同的请求源。 – Machinarius

回答

1

地点PermissionsRequestBrokerPermissionsRequest在一个单独的组件固定在一起,并标记为PermissionsRequest代替internalpublic。然后,如果您需要消费者能够坚持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... */ 
} 
+0

哇。从来没有想过这样一个聪明的解决方案。 – Machinarius

+0

如果请求(或包装器)的使用者在同一个程序集中,那么他们仍然可以创建一个包装器的实例。如果消费者在另一个程序集中被冒用,那么可以简单地使请求的构造函数成为内部的。 – Maarten

+0

I * did * day将它们放入单独的程序集中;)您说得对,您可以不使用包装程序,但如果意图隐藏某些实现细节,则可以这样做。另外,如果'PermissionsRequest'开始变得“​​大”,它不必与'internal' *和*'public'实现混杂在一起。 – Steve

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(); 
    } 
} 
+0

构造函数是私有的,所以不是事件PermissionsRequestBroker可以调用它 – Machinarius

+0

哦,我的坏,我的大脑工作的对立方式,子类可以访问父类的私人东西。 –

+0

没问题。每个人都有这些时刻。 – Machinarius

相关问题