Для меня одной из досадных частей Silverlight является то, что он не позволяет вам возвращать Stream
напрямую, поскольку Silverlight превратит его в Byte[]
даже при использовании TransferMode.StreamedResponse
.Используя эту технику, можно обработать что-то вроде FileStream
потоковым способом из клиента Silverlight ( см. Код ниже ).
Однако я хотел бы сделать что-то подобное с действительно большими C # POCO.Если бы я мог получить Stream
, я мог бы использовать что-то вроде сериализации XML на обоих концах и обрабатывать записи по мере их чтения.Однако, поскольку возвращаемое значение должно быть Byte[]
, я должен прочитать до конца массива, прежде чем смогу его обработать.Этот метод, по крайней мере, позволяет мне предоставить некоторую обратную связь пользователю.
Я предложил две возможности возможных решений.Можно было бы написать свой собственный сериализатор или, по крайней мере, десериализатор, где я обрабатываю данные во время их чтения (я имею в виду текст с разделителями).Другая мысль заключалась бы в создании некоторого типа переменного бита Stream
класса, который, я считаю, потребовал бы от меня крутой кривой обучения.Я ищу любые идеи или ссылки на возможности о том, как обрабатывать значения в Byte[]
во время их чтения.
Сервисный контракт:
public static class Action {
public static string val = "http://tempuri.org/stream";
}
// Share contract between client and server
[ServiceContract]
public interface IFileService {
#if SILVERLIGHT
[OperationContract(AsyncPattern = true, Action = Action.val, ReplyAction = Action.val)]
IAsyncResult BeginReadFile(Message request, AsyncCallback callback, object AsyncState);
system.ServiceMode.Channels.Message EndReadFile(IAsyncResult result);
#else
[OperationContract(AsyncPattern = true, Action = Action.val, ReplyAction = Action.val)]
IAsyncResult BeginReadFile(string filePath, AsyncCallback callback, object AsyncState);
system.IO.Stream EndReadFile(IAsyncResult result);
#endif
}
[DataContract(Name = "ReadFile", Namespace = "http://tempuri.org/")]
public class StreamRequest
{
[DataMember(Order = 1)]
public string FileName;
}
Внедрение услуги:
public IAsyncResult BeginReadFile(string filePath, AsyncCallback callback, object AsyncState) {
return new CompletedAsyncResult<Stream>(File.OpenRead(filePath));
}
public Stream EndReadFile(IAsyncResult result) {
return ((CompletedAsyncResult<Stream>)result).Data;
}
Клиент:
public void ReadFile( string filePath ) {
BackToUIThread backToUIThread = byteCount => {
this.OnBytesReceived(this, new AsyncEventArgs<object>(byteCount));
};
StreamRequest request = new StreamRequest() { FileName = "C:\\test.txt" };
Message mIn = Message.CreateMessage(
_myFactory.Endpoint.Binding.MessageVersion, Action.val, request);
_myService.BeginReadFile(mIn,
(asyncResult) =>
{
Message mOut = _myService.EndReadFile(asyncResult);
System.Xml.XmlDictionaryReader r = mOut.GetReaderAtBodyContents();
r.ReadToDescendant("ReadFileResult"); // move to stream
r.Read(); // move to content
int bytesRead = 1;
long totalBytesRead = 0;
byte[] buffer = new byte[100];
do {
bytesRead = r.ReadContentAsBase64(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
if (bytesRead > 0) {
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(
backToUIThread, totalBytesRead);
}
} while (bytesRead > 0);
r.Close();
mOut.Close();
}, null);
}