Я нашел свой ответ на основе исходного кода Microsoft BinaryWriter по адресу https://referencesource.microsoft.com/#mscorlib / system / io / binarywriter.cs, 08f2e8c389fd32df
Примечание: длина строки записана перед строкой и кодируется 7 битами, размер которых может варьироваться в зависимости от размера строки (> = 128,> = 2 ^ 14,> 2 ^ 21).
Код:
public static int GetBinaryWriterSizeRequired(this string str, Encoding encoding)
{
encoding = encoding ?? Encoding.Default;
int byteCount = encoding.GetByteCount(str);
int byteCountRequiredToWriteTheSize = 1;
// EO: This code is based on the Microsoft Source Code of the BinaryWriter at:
// https://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,2daa1d14ff1877bd
uint v = (uint)byteCount; // support negative numbers
while (v >= 0x80)
{
v >>= 7;
byteCountRequiredToWriteTheSize++;
}
return byteCountRequiredToWriteTheSize + byteCount;
}
Вызов:
...
_writer = new BinaryWriter(_stream);
_writerEncoding = _writer.GetPrivateFieldValue<Encoding>("_encoding");
...
int sizeRequired = name.GetBinaryWriterSizeRequired(_writerEncoding);
Другие (я знаю, что мы не должны вызывать закрытые поля, но я это сделал):
public static T GetPrivateFieldValue<T>(this object obj, string propName)
{
if (obj == null)
throw new ArgumentNullException("obj");
Type t = obj.GetType();
FieldInfo fi = null;
while (fi == null && t != null)
{
fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
t = t.BaseType;
}
if (fi == null)
throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));
return (T)fi.GetValue(obj);
}
Просто для справки, все это плохо:
return Encoding.UTF8.GetByteCount(str) + 1;
return System.Text.ASCIIEncoding.Default.GetByteCount(str) + 1; // sizeof(int); // sizeof int to keep the size
return System.Text.ASCIIEncoding.Unicode.GetByteCount(str) + sizeof(int); // sizeof int to keep the size