创建多个(15岁以上)的HTTP响应滤波器,继承与组合W /注塑 [英] Creating multiple (15+) HTTP Response filters, Inheritance vs. Composition w/ Injection

查看:152
本文介绍了创建多个(15岁以上)的HTTP响应滤波器,继承与组合W /注塑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

先上什么,我试图完成一个小背景故事。

First a little back story on what I am trying to accomplish.

我在创建自定义HTTP模块,其目的是拦截消息给多个(15岁以上)不同的ArcGIS REST Web服务的过程。被拦截的请求和/或响应将被剥夺根据当前用户的任何限制信息。

I am in the process of creating a custom HTTP Module whose purposes is to intercept messages to multiple (15+) different ArcGIS REST web services. The intercepted requests and/or responses will be stripped of any restricted information based on the current user.

例如,返回多层的通话可能某些层剥离出来。

For instance, a call that returns multiple layers might have certain layers stripped out.

未修改响应:

"layers" : [
    {
      "id" : 0, 
      "name" : "Facilities", 
      "parentLayerId" : -1, 
      "defaultVisibility" : true, 
      "subLayerIds" : [1, 2, 3]
    }, 
    {
      "id" : 1, 
      "name" : "Hazardous Sites", 
      "parentLayerId" : 0, 
      "defaultVisibility" : true, 
      "subLayerIds" : null
    }, 
]

修改应答:

"layers" : [
    {
      "id" : 0, 
      "name" : "Facilities", 
      "parentLayerId" : -1, 
      "defaultVisibility" : true, 
      "subLayerIds" : [1, 2, 3]
    }
]

有很多可用的服务,所有这些都通过一个URL唯一标识。每个服务返回非常不同的信息,因此需要过滤不同。此外,每个服务可以以各种格式(HTML,JSON等)返回数据。

There are numerous services available, all uniquely identified via a URL. Each service returns very different information and so needs to be filtered different. Additionally, each service may return the data in a variety of formats (HTML, JSON, etc).

因此​​,我将需要创建不同的过滤器的大量应用到的Htt prequest.Filters和/或Htt的presponse.Filters。

As such, I will need to create a multitude of different filters to apply to HttpRequest.Filters and/or HttpResponse.Filters.

示例:

// Request for layers and the format is JSON
IPolicy policy = GetPolicy(userContext);
Filter filter = new LayerJsonResponseFilter(Response.Filter, policy);
Response.Filter = filter;

请求和响应过滤器从流(或继承自Stream如MemoryStream的另一个类)继承来实现。我希望能够在不重新实现流为每个过滤器轻松地创建新的过滤器。

Request and response filters are implemented by inheriting from Stream (or another class that inherits from Stream such as MemoryStream). I want to be able to easily create new filters without reimplementing Stream for each filter.

一个潜在的解决方案在这里描述wind.com/weblog/posts/72596.aspx

A potential solution is described in here: http://www.west-wind.com/weblog/posts/72596.aspx

但是,我想简化溶液,而不会失去指定许多不同的变换,而不重新实现流的灵活性。我认为我可以做到这一点:

However, I want to simplify the solution without losing the flexibility of specifying many different transformations without reimplementing the stream. I think that I can accomplish this by:


  1. 继承的MemoryStream,从而减少方法的重新实现。

  2. 始终对全部内容进行操作,而不是分块的内容。

  3. 与抽象方法更换事件(例如,过滤器())

  1. Inherit from MemoryStream so as to reduce the reimplementation of methods.
  2. Always operate on full content, rather than chunked content.
  3. Replace the events with an abstract method (e.g., Filter())

我已经考虑两个可能的解决方案。

I have considered two potential solutions.

在这种情况下的每个滤波器包含用于进行过滤的逻辑。将有来自创造一个共同的ResponseFilter抽象基类,像这样所有继承15+过滤器:

In this scenario each filter contains the logic for performing the filtration. There would be 15+ filters created all inheriting from a common ResponseFilter abstract base class like so:

// All filters will inherit from ResponseFilter
public abstract class ResponseFilter : MemoryStream
{
    public ResponseFilter(Stream stream, Policy policy) { }

    // Must be overridden in a derived class with specific Filter logic.
    public abstract string Filter(string content);

    // Overridden to cache content.    
    public override void Write(byte[] buffer, int offset, int count) { }

    // Overridden to perform the filter/transformation before the content is written.
    public override void Flush()
    {
         // Get stream content as a string

         string content = Filter(content);

         // Write new content to stream
    }
}

这将在下面的方式使用。

This would be used in the following way.

// Example
var policy = GetPolicy();
var filter = new MapServiceJsonResponseFilter(response.Filter, policy);
response.Filter = filter;

到该选项的优点是,类的数量被保持为最小。然而,难以在其他地方重用任何滤波器逻辑在​​该应用程序应它成为必要。此外,单元测试过滤器将需要嘲讽流,另一个缺点。

The advantage to this option is that the number of classes is kept to a minimum. However, it becomes difficult to reuse any filter logic anywhere else in the application should it become necessary. Additionally, unit testing the filters would require mocking the Stream, another disadvantage.

在这种情况下,创建了一个单一响应滤波器。实际滤波器逻辑或算法被注入到过滤器。所有的过滤器从一个抽象基类继承FilterBase

In this scenario, a single response filter is created. The actual filter logic or algorithm is injected into the filter. All filters inherit from an abstract base class FilterBase.

// Represents an HttpResponse Filter. Renamed to avoid confusion with
// the filter algorithm.
public class ResponseFilterStream : MemoryStream
{
    public ResponseFilterStream(Stream stream, FilterBase filter) { }

    // Overridden to cache content.    
    public override void Write(byte[] buffer, int offset, int count) { }

    // Overridden to perform the filter/transformation before the content is written.
    public override void Flush()
    {
         // Get stream content as a string

         string content = _filter.Filter(content);

         // Write new content to stream
    }
}

// All filter algorithms inherit from FilterBase and must implement 
// the filter method.
public abstract class FilterBase
{
    protected TransformBase(Policy policy) { }

    // Overridden to perform the filter/transformation.    
    public abstract string Filter(string content);
}

这将在下面的方式使用。

This would be used in the following way.

// Example
var policy = GetPolicy();
var filter = new MapServiceJsonResponseFilter(policy);
ResponseFilter responseFilter = new ResponseFilter(response.Filter, filter);
response.Filter = filter;

到该溶液中的优点是,将过滤的逻辑是完全独立的实现流的任何类。逻辑可以更容易地在必要时重复使用。单元测试是一个稍微简单一些,以及我并不需要模拟的流。

The advantage to this solution is that the filtration logic is completely independent of any classes that implement stream. The logic can be more easily reused if necessary. Unit testing is a little simpler as well as I do not need to mock the stream.

但是,有更多的类(完全1)和用法是稍微更复杂的,虽然不是非常所以

However, there are more classes (exactly 1) and the usage is a little more complex, though not terribly so.

注:我可能要重命名FilterBase,以避免与ResponseFilter混淆。也许TransformBase。

我有,我想,以满足任何一种解决方案几个目标。

I have several goals that I want to meet with either solution.


  1. 解决方案必须高度可测试。单元测试将被用于检查过滤器的正确性。当务之急是测试是尽可能简单。

  2. 解决方案必须易于支持多个过滤器的创建(15 +)。

  3. 该解决方案应该是可读的(即易于维护)。

我认为,解决2是该给定方案的最佳解决方案。我可以用最少的额外的复杂性完全独立的流测试过滤逻辑。无论哪种解决方案将支持#2,#3,因此测试得到的边缘。

I think that solution 2 is the best solution for this given scenario. I can test the filtration logic completely independently of Stream with minimal additional complexity. Either solution will support #2 and #3, so testing gets the edge.

还有什么其他因素可能会有?有没有更好的方法?

What other considerations might there be? Are there better alternatives?

推荐答案

2的解决方案显然是preferable。然而,似乎这个问题的主要症结在于过滤器本身的建设。但愿有过滤器实现中大量的可重复使用的成分。从复合材料部件可以在新的过滤器配置?

Solution 2 is obviously preferable. However, it seems that the major crux of the problem lies in the construction of the Filters themselves. Hopefully there is a lot of reusable composition within the Filter implementations. Can a new filter be "configured" from composite parts?

这篇关于创建多个(15岁以上)的HTTP响应滤波器,继承与组合W /注塑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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