C\#Protobuf 가 0 분배 메모리 의 직렬 화 를 어떻게 하 는 지 상세 하 게 설명 합 니 다.
답 1:
msg.ToByteArray()
이것 은 틀림없이 우리 의 요구 에 부합 되 지 않 을 것 이다.정 답 2:
using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
memoryStream.ToArray();
이 안 에는 memory Stream,coded Output Stream,그리고 ToArray 가 하나의 대상 을 만 들 었 고 Memory Stream 내부 에 byte[]대상 이 하나 더 생 길 수 있 습 니 다.요구 에 부합 되 지 않다
답 3:
어떤 분 이 Memory Stream 에 byte[]slice 를 전달 해서 Memory Stream 에 직접 byte[]를 사용 하 라 고 하 셨 어 요.
var bytes = new byte[msg.CalculateSize()];
using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
이번 소식 은 바로 bytes 안 으로 서열 화 되 었 다.그러나 memory Stream 대상,codec OutputStream 과 memory Stream 내부 의 byte[]가 모두 남아 있 었 다.나 는 대상 을 서열 화 했 지만 쓰레기 대상 이 3 개 생 겼 다. 그래서 CodedOutputStream 류 를 자세히 살 펴 보 겠 습 니 다.
/// <summary>
/// Creates a new CodedOutputStream that writes directly to the given
/// byte array. If more bytes are written than fit in the array,
/// OutOfSpaceException will be thrown.
/// </summary>
public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
{
}
/// <summary>
/// Creates a new CodedOutputStream that writes directly to the given
/// byte array slice. If more bytes are written than fit in the array,
/// OutOfSpaceException will be thrown.
/// </summary>
private CodedOutputStream(byte[] buffer, int offset, int length)
{
this.output = null;
this.buffer = buffer;
this.position = offset;
this.limit = offset + length;
leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
}
byte[]의 구조 함 수 를 제 공 했 지만 slice 의 구조 함 수 를 제공 하지 않 았 습 니 다.다행히 개인 적 인 구조 함수 가 있 습 니 다.답 4:
여 기 는 코드 를 쓰 지 않 습 니 다.아마도 개인 구조 함 수 를 반사 하여 Coded Output Stream 대상 을 구성 하여 Memory Stream 과 그 내부 의 by te 를 절약 하 는 것 입 니 다[].
이제 답 과 비슷 해 졌 습 니 다.
그렇다면 우리 의 문 제 는 CodedOutputStream 마저 줄 일 수 있 느 냐 하 는 것 이다.
정 답 5 가 왔 다.
자세히 살 펴 보 니 이 종 류 는 Stream 을 사용 하지 않 은 상태 에서 buffer,limit,position 몇 명의 멤버 만 수정 하면 됩 니 다.private 멤버 이지 만 C\#는 수정 할 수 있 습 니 다.
내 려 와 서 바로 실천 하 다.
delegate void ClearCodedOutputStream(CodedOutputStream stream, byte[] buffer, int offset, int count);
static ClearCodedOutputStream ResetCodedOutputStream;
static CodedOutputStream codedOutputStream = new CodedOutputStream(new byte[10]);
static unsafe void Encode(IMessage msg, byte[] buffer)
{
ResetCodedOutputStream(codedOutputStream, buffer, 0, buffer.Length);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
}
static Action<T, TValue> MakeSetter<T, TValue>(FieldInfo field)
{
DynamicMethod m = new DynamicMethod(
"setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(Program));
ILGenerator cg = m.GetILGenerator();
cg.Emit(OpCodes.Ldarg_0);
cg.Emit(OpCodes.Ldarg_1);
cg.Emit(OpCodes.Stfld, field);
cg.Emit(OpCodes.Ret);
return (Action<T, TValue>)m.CreateDelegate(typeof(Action<T, TValue>));
}
static void Main(string[] args)
{
var bufferField = typeof(CodedOutputStream).GetField("buffer", BindingFlags.NonPublic | BindingFlags.Instance);
var limitField = typeof(CodedOutputStream).GetField("limit", BindingFlags.NonPublic | BindingFlags.Instance);
var positionField = typeof(CodedOutputStream).GetField("position", BindingFlags.NonPublic | BindingFlags.Instance);
var setLimit = MakeSetter<CodedOutputStream, int>(limitField);
var setPosition = MakeSetter<CodedOutputStream, int>(positionField);
var setBuffer = MakeSetter<CodedOutputStream, byte[]>(bufferField);
ResetCodedOutputStream = (stream, buffer, offset, length) =>
{
//this.buffer = buffer;
//this.position = offset;
//this.limit = offset + length;
setBuffer(stream, buffer);
setPosition(stream, offset);
setLimit(stream, offset + length);
};
var buffer = new byte[msg.CalculateSize()];
Encode(msg, buffer);
}
이 인 스 턴 스 코드 에는 static 의 전역 Coded Output Stream 을 사 용 했 습 니 다.진정 으로 사용 할 때 스 레 드 안전 을 확보 해 야 합 니 다.그래서 다음 문 제 는:
1.CodedOutput Stream 대상 스 레 드 의 안전 을 어떻게 보장 합 니까?
2.var buffer=new byte[msg.Calculate Size()];이것 도 아 껴.
이 두 문 제 는 독자 에 게 생각 하도록 남 겨 두 었 다.
Github: http://github.com/egmkang
C\#Protobuf 가 0 분 배 된 메모리 의 직렬 화 를 어떻게 하 는 지 에 대한 자세 한 설명 은 여기까지 입 니 다.더 많은 관련 C\#Protobuf 직렬 화 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.