Регистрация произвольного объекта обработки данных в потоке байтов - PullRequest
3 голосов
/ 27 апреля 2011

Мне необходимо предоставить возможность подключить произвольный класс C #, написанный третьей стороной, к существующей программе, чтобы она могла обрабатывать поток байтов.

Этот объект (или его тип) будет зарегистрирован с отправляющим и получающим объектом.Он считывает байты из отправляющего объекта, обрабатывает их некоторым образом и передает их получающему объекту, например:

Sender ==> Filter ==> Receiver

API-интерфейс прототипа для класса фильтра выглядит примерно так:

// Reads the specified number of bytes from the receiver
public byte[] ReadBytes(int numberOfBytes)

// Writes the specified number of bytes to the sender.
public void WriteBytes(byte[] data)

Как я могу предоставить относительно простой механизм для регистрации объекта Filter с объектами Sender и Receiver, а затем подключить методы, чтобы байты данных могли быть переданы в объект Filter и на другую сторону?


Предостережения:

  1. Моя организация имеет некоторую аллергию на Open Source, поэтому такие структуры, как MEF, вероятно, отсутствуют.
  2. Если вы рекомендуете шаблон GoF, пожалуйста, объясните подробно , как он относится к этой конкретной проблеме.

Ответы [ 2 ]

1 голос
/ 27 апреля 2011

Я не уверен, что я полностью понимаю проблему, однако из того, что вы описали, я, вероятно, имею фильтр и Sender оба реализуют (или предоставляют экземпляр) Поток с CanRead , возвращающим false.

Для фильтра потребуется экземпляр Sender для чтения байтов, поэтому фильтр должен наследовать от некоторого базового класса, который позволил бы кому-то предоставить источник Stream, что-то вроде:

public abstract class FilterBase : Stream
{
    private readonly Stream sender;
    protected Stream Sender
    {
        get { return sender; }
    }

    public FilterBase(Stream sender)
    {
        this.sender = sender;
    }
}

Чтобы «зарегистрировать» фильтр у отправителя, вы просто предоставляете экземпляр Stream, из которого фильтр должен читать байты.

Точно так же, чтобы «Зарегистрировать» фильтр в Приемнике, просто дайте ему экземпляр Stream (фильтр), из которого он должен читать байты. (В качестве альтернативы вы можете предоставить Type и заставить получателя / отправителя создать экземпляр фильтра - это бит, на котором я нечеткий).

Это позволяет легко объединять любое количество фильтров.

Для удобства FilterBase может реализовывать многие из методов и свойств Stream (большинство из них просто выбросит NotSupportedException в любом случае).

В качестве альтернативы вы можете определить свой собственный интерфейс IStream (или IFilter), который использует только те методы, которые использует получатель, но я все равно использовал бы тот же шаблон цепочки, в котором вы «регистрируете» отправителя / получателя с помощью фильтровать, предоставляя экземпляр IStream.

Конечно, это работает, только если Receiver извлекает байты из Sender - если Sender вместо этого переводит байты в Receiver, тогда вашему фильтру потребуется реализовать Write методы потока вместо Read методы и Receiver должны наследовать (или предоставлять) Stream.

Вы также можете сделать и то, и другое, если это необходимо, если Sender и Reciever наследуют (или предоставляют) Stream. Это может сбить с толку любого, кто применяет фильтр: методы Write - это сообщения, которые нужно отправить получателю, а методы Read - это запросы на чтение от отправителя. Возможно, вы захотите создать свой собственный интерфейс (ы), чтобы было ясно, каковы роли, однако опять-таки я бы следовал тому же шаблону - только с разными именами методов.

1 голос
/ 27 апреля 2011

Вы можете инкапсулировать свой API вместе с объектами отправителя и получателя в класс StreamContext и затем передать объект контекста в фильтр, который может реализовать интерфейс IFilter:

public class StreamContext
{ 
    private Sender sender;
    private Receiver receiver;

    public byte[] ReadBytes(int numberOfBytes) 
    { 
        return readBytesFromSender(numberOfBytes); 
    }

    public void WriteBytes(byte[] data) 
    { 
        writeToReceiver(data); 
    }
}

public interface IFilter
{
    void Filter(StreamContext context);
}
...