역 직렬화 할 때 직렬화 된 스트림의 다음 '항목'을 건너 뛸 수 있습니까? 플러그인 지향 아키텍처와 관련하여 직렬화 된 개체 그래프의 개별 부분이 다른 환경에서 알 수없는 유형이 될 수 있습니다 (안전하게 무시할 수 있다고 가정). 이들을 역 직렬화하려고하면 물론 실패합니다.
abstract class Thing{}
class OneThing : Thing {} // <-- known in environment A & B
class SomeThing : Thing {} // <-- only known in environment A
...
var things = new List<Thing>();
...
things.Add( (OneThing)(formatter.Deserialize(stream)) );
things.Add( (SomeThing)(formatter.Deserialize(stream)) ); // <-- skip in B
things.Add( (OneThing)(formatter.Deserialize(stream)) );
바이너리 포맷터로 어떻게 작동합니까? 길이를 계산하고 직렬화 된 항목의 모호하지 않은 유형 이름 (예 : 문자열)을 검색하고 항목 바로 앞에 저장해야하나요? 그러면 직렬화 해제 할 때 건너 뛸 수 있습니다 (스트림 포인터를 증가시켜)? 아니면 직렬화 된 표현의 문제가 적은 조작으로 더 나은 대안이 있습니까?
나는 포인터를 증가 시켜서 스트림 부분을 간단히 건너 뛰는 버전을 시도했다. 현재로서는 이것이 나를 위해 작동합니다 (가장 좋은 해결책이 아닐 수도 있음).
interface ISerializableObject { }
class PluginSerialization
{
private readonly IFormatter formatter;
public PluginSerialization(IFormatter f)
{
formatter = f;
}
public void SerializeToStream(IEnumerable<ISerializableObject> components, Stream s)
{
foreach (var component in components)
{
using (var cStream = new MemoryStream())
{
formatter.Serialize(cStream, component);
cStream.Flush();
// write to stream [length] [type as string] [object]
formatter.Serialize(s, cStream.Length);
formatter.Serialize(s, component.GetType().ToString());
cStream.WriteTo(s);
}
}
}
public List<ISerializableObject> DeserializeFromStream(Stream s, Func<string, bool> isKnownType )
{
var components = new List<ISerializableObject>();
while (s.Position < s.Length - 1)
{
var length = (long)(formatter.Deserialize(s));
var name = (string)(formatter.Deserialize(s));
// skip unknown types
if (!isKnownType(name))
{
s.Position += length;
continue;
}
components.Add((ISerializableObject) (formatter.Deserialize(s)));
}
return components;
}
}
이를 통해 다른 객체 목록 ( List<ISerializableObject>()
) 을 부분적으로 역 직렬화 할 수 있습니다 . 그러나 데이터가 저장되는 방식과 순서 (길이, 유형 이름, 객체)는 특정 구현 세부 사항이므로 가능한 한 최대한 캡슐화해야합니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다