2011-07-27 3 views
0

C# 4에서 작성된 자동화 추가 기능 (일부는 이진 직렬화 된 데이터를로드하려고합니다)이 있습니다. 나는 (직렬화 및 역 직렬화 모두)을 AssemblyFormat를 설정하고있어 경우 BinaryFormatter에자동화 추가 기능에서 C# 직렬화가 실패하지만 NUnit 테스트에서는 수행되지 않습니다.

Unable to find assembly 'XXX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. 
    at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly() 
    at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name) 
    at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable) 
    at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record) 
    at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum) 
    at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run() 
    at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) 
    at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) 
    at 

다음과 같습니다 : 엑셀 내에서 실행하는 경우는 단위 테스트에서 완벽하게 작동하지만, 실패

serializationCodec.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple; 

을 어느 I 생각은 here에 따라 버전을 무시합니다.

그런 다음 Excel의 "신뢰할 수있는 위치"개념 때문일 수 있으므로 프로젝트 디렉토리를 추가하고 모든 하위 디렉토리를 선택했지만 오류가 남아 있습니다.

헛된 것은 System.Runtime.Serialization.OptionalFieldAttribute 특성을 추가하려고했지만 도움이되지 않았습니다.

단위 테스트는 자체적으로 생성 된 직렬화 된 파일이나 Excel에서 실행 된 동일한 코드를로드 할 수 있지만 Excel에서는 실제 직렬화를 수행했는지 여부에 관계없이 직렬화 된 데이터를로드 할 수 없습니다.

Excel에서 직렬화 된 내용을 deserialize 할 수 없다는 사실은 사용 된 어셈블리에 대한 액세스 권한을 분명히 가지고 있기 때문에 이것이 재사용된다는 것을 암시합니다.

그래서 Excel이 내 단위 테스트와 비교하여 다른 방식으로 deserialize됩니까? (또는 더 중요한 것은, 어떻게 deserialization을 Excel에서 사용할 수 있습니까?)

감사합니다.

+0

업데이트 : AssemblyFormat 설정을 제거하면 상황을 개선하지 않습니다.이것이 존재하는 유일한 이유는 단위 테스트를 돕는 것입니다 (이전의 직렬화 된 데이터를로드하는 것입니다). – earcam

+0

저는 이것이 경고를 생성하는 [ClassInterface (ClassInterfaceType.AutoDual)] 때문이라고 확신합니다. "... ClassInterface (ClassInterfaceType .AutoDual) 제대로 작동하지 않을 수 있습니다 ... "code : CA1408. 그래서 지금은 자동화 추가 기능이 UDF를 등록하고 IDTExtensibility2를 구현하여 Excel.Application에 대한 핸들을 얻을 수있는이 ClassInterface를 제거하는 방법을 찾아야합니다. – earcam

답변

0

나는 붉은 색 청어를 쫓아 갔고 버전 문제 (전 shims와 모든 종류를 보았습니다)라는 가정하에 어디에도 없습니다.

사실 그것은 이상한 어셈블리 바인딩 때문이었습니다. 자동화 addin의 DLL은 종속 된 DLL에서 클래스를보고로드 할 수 있지만 필요한 어셈블리를 찾지 못한 경우 deserialization 할 수있는 경우에는 deserialization 호출이 DLL에 속한 클래스의 것이기는하지만 발견! 클래스 X 내부

, 클래스 Y 및 Z에 따라 달라집니다

솔루션은 확실히 해킹하지만 난이었다 같은 경우에 다른 사람이 붙어 그래서이 과거 나있어, 여기에 해킹 (들)의 (ProjectForX, ProjectForY 및 ProjectForZ 이름) 각각의 프로젝트 DLL을

private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) 
    { 
     if(args.Name.StartsWith("ProjectForX,")) { 
      return typeof(X).Assembly; 
     } else if(args.Name.StartsWith("ProjectForY,")) { 
      return typeof(Y).Assembly; 
     } else if(args.Name.StartsWith("ProjectForZ,")) { 
      return typeof(Z).Assembly; 
     } 
     return null; 
    } 


    public static X LoadX(string filename) 
    { 
     AppDomain currentDomain = AppDomain.CurrentDomain; 
     ResolveEventHandler handler = new ResolveEventHandler(MyResolveEventHandler); 
     currentDomain.AssemblyResolve += handler; 
     try { 
      Stream stream = new FileStream(@filename, FileMode.Open); 
      try { 
       BinaryFormatter deserializer = createBinaryFormatter(); 
       X model = (X)deserializer.Deserialize(stream); 
       return model; 
      } finally { 
       stream.Close(); 
      } 
     } finally { 
      currentDomain.AssemblyResolve -= handler; 
     } 
    } 

에서 각각 기본적으로 그냥 해결 이벤트에 후크와 요청 된 유형 이름에 따라 올바른 어셈블리를 제공합니다 -이 특히 안전하지 않다 (I ' 어셈블리 디스크립터의 쉼표를 사용하여 충돌을 최소화하려고 시도합니다.

분명히이 작업을 수행하는 확실한 방법이 있으며이 문제는 구성이 좋지 않아 MS 제품 및 C#에 대한 제한된 경험 일뿐입니다. 난 그냥 모 놀리 식 DLL을 구축하려는 경우

는) = 문제가 없었을 것입니다

관련 문제