2012-11-19 2 views
0

저는 Protobuf-net을 사용하여 직렬화를 위해 binaryformatter를 대체하려고합니다. 나는 여러 가지 문제에 직면 해 있으며 일을하는 데 권장되는 방법이 궁금합니다. 일련 번호를 지정하고 싶습니다. 그들은 솔루션의 여러 프로젝트에 있습니다.binaryformatter를 Protobuf-net으로 바꾸십시오.

직렬화 할 클래스가있는 동일한 프로젝트에서 직렬화를 호출하려고하면 다른 프로젝트에있는 경우 계약을 알지 못해 작동합니다. 우리의 클래스는 다른 프로젝트에 정의 된 유형 (구조체)을 사용합니다. 이 구조체를 사용하여 클래스를 직렬화하려고하면 해당 유형에 대해 알지 못하는 것과 동일한 문제가 발생합니다. PrepareSerializer를 사용하여 수동으로 유형을 추가 할 수 있으며 직렬화 할 것입니다 ...하지만 Deserialize하려고하면 부분적으로 신뢰할 수있는 호출자에 대한 오류가 발생합니다.

또한 프리 컴파일 유틸리티를 사용하려고 시도했지만 클래스는 공용 접근자를 사용하여 private 필드를 사용하므로 private 필드를 처리 할 수 ​​없다는 오류가 발생하여 바이너리 포맷터를 대체 할 수 없습니다.

어떻게 이러한 문제를 해결할 수 있습니까?

"That assembly does not allow partially trusted callers." 
at proto_4(Object , ProtoReader) 
    at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) 
    at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) 
    at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type) 
    at ProtoBuf.ProtoReader.ReadObject(Object value, Int32 key, ProtoReader reader) 
    at proto_2(Object , ProtoReader) 
    at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) 
    at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) 
    at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) 
    at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) 
    at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) 
    at ProtoBuf.Serializer.Deserialize[T](Stream source) 
    at BinarySerializationTest.Form1.button1_Click(Object sender, EventArgs e) 
    at System.Windows.Forms.Control.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnClick(EventArgs e) 
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) 
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ButtonBase.WndProc(Message& m) 
    at System.Windows.Forms.Button.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
    at System.Windows.Forms.Application.Run(Form mainForm) 
    at BinarySerializationTest.Program.Main() 
    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

답변

0

재미있는 : -

편집이는 부분적으로 신뢰할 수있는 호출자 예외의 스택 트레이스입니다. 난 부분 신뢰 설정으로 많은 일을하지 못했지만 stacktrace가 불어 올 때 (그리고 당신이 호출하는 곳, 즉 serialize를 호출하는 어셈블리가 deserialize를 호출하는 어셈블리와 다른지)를 알 수 있다면, 나는 몇 군데에 [AllowPartiallyTrustedCallers]을 추가하여 작동되도록 할 수 있습니다.

프리 컴파일 경로는 내 다른 제안 이었지만 독립 실행 형 어셈블리의 액세스 가능성이보다 엄격하기 때문에 실제로는 개인 필드와 함께 사용할 수 없습니다.

세 번째 옵션은 영향을받는 private 필드를 internal 필드로 만들고 [assembly:InternalsVisibleTo("NameOfGeneratedAssembly)]을 사용하여 해당 필드를 액세스 가능하게 만든 다음 "프리 컴파일러"를 사용하는 것입니다. 그러면이 필드에 액세스 할 수 있으며 r602 이후부터 지원됩니다 (작성 당시 최신 빌드).

+0

Marc, 나는 사전 컴파일을 시도하고 어떻게되는지 알려줄 것입니다. 다른 (잠재적으로 어리석은) 질문 - 프리 컴파일러로. 개인 필드에 액세스 할 수없는 이유는 무엇입니까? 클래스가 [Protocontract (AllFields)]로 장식되어 있다면 (틀린 문법이지만, 내가 의미하는 것을 안다.), 시리얼 라이저는 아마도 리플렉션을 통해 비공개 필드에 액세스 할 것인가? 왜 프리 컴파일러가 그렇게 할 수 없습니까? –

+0

@Colin은 어셈블리에서 유효하지 않기 때문에 유효성 검사에 실패하고 CLI에 의해 거부됩니다. 그러나'internal' +'[InternalsVisibleTo (...)] 트릭은 CLI와 프리 컴파일러 모두에서 완전히 허용됩니다. Re가 CompileInPlace와 함께 작동하는 이유 : 메모리 내에서 작업 할 때 더 많이 속일 수 있습니다. 정보를 위해서, 이것은'XmlSerializer'가 public 멤버만을 허용하는 이유이기도합니다 - 그것은 어셈블리를 생성합니다. –

+0

프리 컴파일은 내 테스트 프로젝트에서 그 트릭과 함께 작동합니다. 그것을 전체 솔루션에 연결하고 이것이 어떻게 진행되는지보십시오. –

관련 문제