Как я реализую Быстрый взгляд () функция на DataReader?

Вот альтернатива, вместо добавления файла incomplete.flag к каждому каталогу, который вы хотите исключить, сгенерируйте файл, содержащий список всех каталогов, которые вы хотите исключить, и затем используйте атрибут excludesfile. Примерно так:

<fileset dir="${basedir}" excludesfile="FileWithExcludedDirs.properties">
  <include name="locale/"/>
  <exclude name="locale/*/incomplete.flag">
</fileset>

Надеюсь, это поможет.

7
задан Gabe Moothart 21 May 2009 в 17:42
поделиться

3 ответа

Я бы предложил что-то похожее на решение Джейсона, но с использованием оболочки, реализующей вместо этого IDataReader, поэтому:

sealed public class PeekDataReader : IDataReader
{
    private IDataReader wrappedReader;
    private bool wasPeeked;
    private bool lastResult;

    public PeekDataReader(IDataReader wrappedReader)
    {
        this.wrappedReader = wrappedReader;
    }

    public bool Peek()
    {
        // If the previous operation was a peek, do not move...
        if (this.wasPeeked)
            return this.lastResult;

        // This is the first peek for the current position, so read and tag
        bool result = Read();
        this.wasPeeked = true;
        return result;
    }

    public bool Read()
    {
        // If last operation was a peek, do not actually read
        if (this.wasPeeked)
        {
            this.wasPeeked = false;
            return this.lastResult;
        }

        // Remember the result for any subsequent peeks
        this.lastResult = this.wrappedReader.Read();
        return this.lastResult;
    }

    public bool NextResult()
    {
        this.wasPeeked = false;
        return this.wrappedReader.NextResult();
    }

    // Add pass-through operations for all other IDataReader methods
    // that simply call on 'this.wrappedReader'
}

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

Использование:

using (IDataReader reader = new PeekDataReader(/* actual reader */))
{
    if (reader.Peek())
    {
        // perform some operations on the first row if it exists...
    }

    while (reader.Read())
    {
        // re-use the first row, and then read the remainder...
    }
}

Однако обратите внимание, что каждый вызов Peek () фактически переходит к следующей записи, если предыдущая операция не была также Peek (). Сохранение этой симметрии с операцией Read () обеспечивает более простую реализацию и более элегантный API.

5
ответ дан 6 December 2019 в 21:18
поделиться

Вы можете создать конечный автомат, который отслеживает сравнение режима быстрого просмотра и обычного режима. Может быть, что-то вроде этого (можно было бы просто перебросить их все в один файл под названием Peeker.cs или что-то в этом роде):

public sealed class Peeker
{
    internal readonly PeekMode PEEKING;
    internal readonly NormalMode NORMAL;

    private ReadState _state;

    public Peeker()
    {
        PEEKING = new PeekMode(this);
        NORMAL = new NormalMode(this);

        // Start with a normal mode
        _state = NORMAL;
    }

    public object[] OnRead(IDataReader dr, bool peek)
    {
        return _state.OnRead(dr, peek);
    }

    internal void SetState(ReadState state)
    {
        _state = state;
    }
}

internal abstract class ReadState
{
    protected Peeker _peeker;

    protected ReadState(Peeker p)
    {
        _peeker = p;
    }

    public abstract object[] OnRead(IDataReader dr, bool peek);        
}

internal class PeekMode : ReadState
{
    public PeekMode(Peeker p)
        : base(p)
    {
    }

    public override object[] OnRead(IDataReader dr, bool peek)
    {
        object[] datarow = new object[dr.FieldCount];

        if (peek)
        {                
            dr.GetValues(datarow);                
        }
        else
        {
            if (dr.Read())
            {
                dr.GetValues(datarow);
                _peeker.SetState(_peeker.NORMAL);
            }
        }

        return datarow;
    }
}

internal class NormalMode : ReadState
{
    public NormalMode(Peeker p)
        : base(p)
    {
    }

    public override object[] OnRead(IDataReader dr, bool peek)
    {
        object[] datarow = new object[dr.FieldCount];

        if (peek)
        {
            if (dr.Read())
            {
                dr.GetValues(datarow);
                _peeker.SetState(_peeker.PEEKING);
            }
        }
        else
        {
            if (dr.Read())
            {
                dr.GetValues(datarow);
            }
        }

        return datarow;
    }
}

Немного перебор, но ладно.

Чтобы использовать это, вы просто сделаете следующее:

Peeker p = new Peeker();
.
.
.
SomeDataReaderType dr = SomeCommandType.ExecuteReader();
.
.
.
// To peek
object[] myDataRow = p.OnRead(dr, true);

// or not to peek
object[] myDataRow = p.OnRead(dr, false);

] Затем сделайте то, что вам нужно, со своей строкой. Возможно, есть способ лучше, чем использование массива объектов, но суть вы поняли.

Удачи!

4
ответ дан 6 December 2019 в 21:18
поделиться

Вам не нужен метод Peek (). Вы можете выполнить то, что вам нужно, с помощью цикла Do While.

Так что вместо

while(dr.read())
{
  ... do stuff
}

вы должны

dr.read();
... do stuff

do
{
  ... do stuff
}while(dr.read())
3
ответ дан 6 December 2019 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: