安全地提供公开的API(只读)和私有API的对象(读写) [英] An object that securely provides both public API (read-only) and private API (read-write)

查看:257
本文介绍了安全地提供公开的API(只读)和私有API的对象(读写)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个结构问题。程序员遇到这个问题的封装很多时候,但我还没有看到一个完整而清晰的解决方案。

This is an architecture problem. Programmers encounter this encapsulation problem quite often, but I haven't yet seen a complete and clean solution.

相关问题:

<一个href=\"http://stackoverflow.com/questions/10014984/readonly-class-design-when-a-non-readonly-class-is-already-in-place\">readonly一流的设计,当一个非只读类是已经到位

<一个href=\"http://stackoverflow.com/questions/10890695/controlling-read-write-access-to-fields\">Controlling读田/写访问

通常,在OOP范式,对象存储领域他们的数据。类自己的方法可以完全访问其字段。当你需要返回值,只返回数据的副本,使外界code不能中断数据。

Normally, in OOP paradigm, objects store their data in fields. The class' own methods have full access to its fields. When you need to return value, you just return a copy of the data, so that the outside code cannot break the data.

现在假设数据段是复杂的,所以他们自己的类对象封装并且这些对象不能容易地被复制。现在,如果你从某些属性返回这样的对象,外面code有其相同的访问您的内部code。例如,如果您返回列表与LT; INT&GT; ,每个人都可以值添加到它。这通常是不希望的。

Now suppose that the data pieces are complex, so they're themselves encapsulated in class objects and that these objects cannot be easily copied. Now, if you return such object from some property, the outside code has the same access to it as your internal code. For example, if you return a List<int>, everyone can add values to it. This is usually undesirable.

这个问题通常是工作围绕使用只读包装 - 您在返回之前包裹在只读包装您的完全访问内部对象。这种方法的问题在于,该包装可以是用于包装的值的差取代 - 的包装是一个不同的类。 (如果您从这个修改类(或反之亦然只读包装),那么任何人都可以向上转换/向下转换的只读对象到修改的对象,打破了保护。)

This problem is usually worked around using read-only wrappers - you wrap your full-access internal objects in read-only wrappers before returning. The problem with this approach is that the wrapper may be a poor substitution for the wrapped value - the wrapper is a different class. (And if you derive the read-only wrapper from the modifiable class (or vise-versa), then anybody can up-cast/down-cast the "read-only" object to the modifiable object, breaking the protection.)

我要一个模式使得:


  • 的数据(例如,一个 INT 值)的公共/只读API和私人/修改API。

  • 只有对象创建者获得了私有/修改API。

  • 私人/公共API可以有两种无源器件(例如方法,属性)和有源部件(例如事件)。

  • 代表不应除了在对象创建阶段使用。所有电话应该是直接的。

  • 从公共/只读API内部数据访问(和,preferably,从民营/修改API太)应尽可能直接。我不想包装的一大叠撰写这些对象时累积。

  • The data (say, an int value) has "public/read-only API" and "private/modifiable API".
  • Only the object creator has access to the "private/modifiable API".
  • The private/public APIs may have both passive parts (e.g. methods, properties) and active parts (e.g. events).
  • Delegates should not be used except at the object creation stage. All calls should be direct.
  • The access to the internal data from the "public/read-only API" (and, preferably, from the "private/modifiable API" too) should be as direct as possible. I don't want a big stack of wrappers to accumulate when composing such objects.

下面是样本接口:

interface IPublicApi {
    int GetValue();
}

interface IPrivateApi {
    void SetValue(int value);
}

interface IPrivateConsumer {
    void OnValueChanged(); //Callback
}

我设计这样的方案。我想你批评我的解决方案,或者给自己的解决方案。

I have devised such scheme. I want you to critique my solution or give your own solution.

推荐答案

有有必须解决的几个子问题。

There are several sub-problems that have to be solved.


  1. 如何让私有APIcode来访问私人数据,而不允许外界code调用它?

  2. 如何给私有API访问对象的创建者?

  3. 如何使用私有API(呼叫/获取调用)建立对象和code之间的双向沟通​​?

我的系统是由这些类的:

My system consists of these classes:

ReadableInt 是公共API

ReadableInt.PrivateApi 是原始私有API的代理对象

ReadableInt.PrivateApi is the raw private API proxy object

ReadableInt.IPrivateConsumer 是公众对私人回调接口

ReadableInt.IPrivateConsumer is the public-to-private callback interface

public sealed class ReadableInt {
    int _value;
    IPrivateConsumer _privateConsumer;

    public ReadableInt(IPrivateConsumer privateConsumer, Action<PrivateApi> privateConsumerInitializer) {
        _privateConsumer = privateConsumer;
        var proxy = new PrivateApi(this);
        privateConsumerInitializer(proxy);
    }
    public int GetValue() {
        return _value;
    }        
    private void SetValue(int value) {
        _value = value;
        _privateConsumer.OnValueChanged();
    }

    public interface IPrivateConsumer {
        void OnValueChanged();
    }

    public class PrivateApi {
        ReadableInt _readableInt;

        internal PrivateApi(ReadableInt publicApi) {
            _readableInt = publicApi;
        }

        public void SetValue(int value) {
            _readableInt.SetValue(value);
        }
    }
}

WritableInt 是一些私有API的消费者,这可能位于另一个装配。

WritableInt is some private API consumer, which may reside in another assembly.

public sealed class WritableInt : ReadableInt.IPrivateConsumer {
    ReadableInt _readableInt;
    ReadableInt.PrivateApi _privateApi;

    public WritableInt() {
        _readableInt = new ReadableInt(this, Initialize);
    }

    void Initialize(ReadableInt.PrivateApi privateApi) {
        _privateApi = privateApi;
    }

    public ReadableInt ReadOnlyInt { get { return _readableInt; } }

    public void SetValue(int value) {
        _privateApi.SetValue(value);
    }

    void ReadableInt.IPrivateConsumer.OnValueChanged() {
        Console.WriteLine("Value changed!");
    }
}

一个可以使用的类是这样的:

One can use the classes like this:

var writeableInt = new WritableInt();
var readableInt = writeableInt.ReadOnlyInt;

这是系统如何工作的:


  • 私有API( ReadableInt.PrivateApi )获得访问的主要对象( ReadableInt )由是私有成员一个内部类。没有了铸造/向下铸造安全漏洞。

  • 请注意, ReadableInt.PrivateApi 构造标记内部,所以只有 ReadableInt 可以创建一个实例。我无法找到一个更优雅的方式来从创建prevent任何人 ReadableInt.PrivateApi ReadableInt 对象

  • 在一般情况下, ReadableInt 需要私有API消费者参考称呼它(通知等)。脱钩从具体的私有API消费者的公共API,私有API消费者抽象为 ReadableInt.IPrivateConsumer 接口。 ReadableInt 通过构造函数接收参照 ReadableInt.IPrivateConsumer 对象。

  • 私有API控制器对象( ReadableInt.PrivateApi )是考虑到创建者( WriteableInt ),通过回调( 动作&LT; PrivateApi&GT; )传递到 ReadableInt 构造函数。 这是非常难看。任何人都可以提出另一种方式?

  • 有一个小问题: WritableInt.OnValueChanged()方法是私有的,而且是有效的公众,因为它的接口方法。这可以用一个代表或代理来解决。有没有其他办法?

  • The private API (ReadableInt.PrivateApi) gains access to the main object (ReadableInt) private members by being an inner class. No up-casting/down-casting security breaches.
  • Notice that the ReadableInt.PrivateApi constructor is marked internal, so only ReadableInt can create the instances. I could not find a more elegant way to prevent anyone from creating a ReadableInt.PrivateApi from a ReadableInt object.
  • In general, ReadableInt needs a reference to the private API consumer to call it (notifications etc.). To decouple the public API from concrete private API consumers, the private API consumer is abstracted as the ReadableInt.IPrivateConsumer interface. ReadableInt receives the reference to a ReadableInt.IPrivateConsumer object through the constructor.
  • The private API controller object (ReadableInt.PrivateApi) is given to the creator (WriteableInt) via callback (Action<PrivateApi>) passed to the ReadableInt constructor. It's extremely ugly. Can anyone propose another way?
  • There is a small problem: WritableInt.OnValueChanged() method is private, but is effectively public as it's an interface method. This can be solved with a delegate or a proxy. Is there any other way?

本系统的工作原理,但有一些地方我不是感到自豪。我特别不喜欢的初始化阶段时,所有部件链接在一起。这能在某种程度上简化?

This system works, but has some parts that I'm not proud of. I particularly dislike the initialization stage when all parts are linked together. Can this be simplified somehow?

这篇关于安全地提供公开的API(只读)和私有API的对象(读写)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆