Как инициализировать байтовый массив как параметр OUT в C # до того, как станет известна правильная длина массива - PullRequest
1 голос
/ 30 августа 2011

У меня проблемы с веб-методом, который используется для загрузки файла в вызывающий файл HTTPHandler.ashx. Обработчик вызывает веб-метод следующим образом:

byte[] docContent;
string fileType;
string fileName;
string msgInfo = brokerService.DownloadFile(trimURL, recNumber, out docContent, out fileType, out fileName);

В вызываемом webmethod я должен инициализировать массив байтов перед его использованием, или я получаю ошибки компилятора во всех операторах возврата:

The out parameter 'docContents' must be assigned to before control leaves the current method

Я попытался установить его в пустой массив, но это приводит к сбою метода Buffer.BlockCopy:

Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
mscorlib
  at System.Buffer.BlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count)

Я знаю, что мне нужно его инициализировать, но я не знаю длины необходимого массива, пока не получу доступ к базе данных. Посредством отладки я проверил, что весь код работает, за исключением Buffer.BlockCopy:

    public string DownloadFile(string trimURL
        , string TrimRecordNumber
        , out byte[] docContents
        , out string returnFiletype
        , out string returnFilename)
    {
        docContents = new byte[0];
        returnFiletype = null; returnFilename = null;
        try
        {
            ConnectToTrim(trimURL);
            if (!db.IsValid)
                return "CRITICAL: Database Is NOT Valid";
            Record myRec = db.GetRecord(TrimRecordNumber);
            if (myRec == null)
                return "CRITICAL: Record not found.";
            uint bufferSize = 10000;
            int documentLength = myRec.DocumentSize;
            byte[] result = new byte[documentLength];
            byte[] buffer = new byte[bufferSize];
            uint bytesRead;
            uint totalBytesRead = 0;
            TRIMSDK.IStream docStream = myRec.GetDocumentStream(string.Empty, false, string.Empty);
            while (totalBytesRead < documentLength)
            {
                docStream.RemoteRead(out buffer[0], 10000, out bytesRead);
                for (int i = 0; i < bytesRead; i++)
                {
                    result[totalBytesRead] = buffer[i];
                    totalBytesRead += 1;
                }
            }
            returnFiletype = myRec.Extension;
            returnFilename = myRec.SuggestedFileName;
            Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
            return string.Format("OK-Document for recordnumber({0}): {1}.{2} - size: {3} bytes",
                TrimRecordNumber, returnFilename, returnFiletype, Convert.ToString(documentLength)); 
        }
        catch (Exception ex)
        {
            return LogException(ex, "CRITICAL: Exception in DownloadFile method has been logged:", trimURL, 100);
        } 
    } 

1 Ответ

5 голосов
/ 31 августа 2011

Вы можете начать с инициализации его до нуля.Непосредственно перед вызовом Buffer.BlockCopy, выделите и инициализируйте его для правильной длины.

Это будет выглядеть так:

public string DownloadFile(string trimURL
    , string TrimRecordNumber
    , out byte[] docContents
    , out string returnFiletype
    , out string returnFilename)
{
    docContents = null;

    //...

        returnFiletype = myRec.Extension;
        returnFilename = myRec.SuggestedFileName;
        docContents = new byte[result.Length]; // Allocate appropriately here...
        Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
        return ...

В качестве альтернативы, вы можете просто напрямую выделить и скопировать результаты в docContents - полностью исключает необходимость в result.Однако вам все равно нужно будет инициализироваться до null в начале, если вы хотите оставить общий контроль потока в покое.

...