유형을 직렬화하려고 할 때 작업했던 응용 프로그램이 실패합니다.
다음과 같은 진술
XmlSerializer lizer = new XmlSerializer(typeof(MyType));
생산 :
System.IO.FileNotFoundException occurred
Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Source="mscorlib"
FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
FusionLog=""
StackTrace:
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
클래스에 대한 특수 직렬 변환기를 정의하지 않습니다.
이 문제를 어떻게 해결할 수 있습니까?
답변
믿거 나 말거나, 이것은 정상적인 행동입니다. 예외는 발생하지만 XmlSerializer에서 처리되므로 예외를 무시하면 모든 것이 잘 진행됩니다.
나는 이것이 매우 성가신 것을 발견했으며 조금 둘러 보면 이것에 대해 많은 불만이 있었지만, 내가 읽은 것에서 그것에 대해 아무것도 할 계획이 없습니다.
특정 예외에 대한 첫 번째 예외를 해제하면 디버깅하는 동안 항상 예외 팝업이 표시되는 것을 피할 수 있습니다. Visual Studio에서 디버그 -> 예외 (또는 Ctrl+ Alt+ E), 공용 언어 런타임 예외 -> System.IO- > System.IO.FileNotFoundException으로 이동하십시오 .
블로그 게시물 C # XmlSerializer FileNotFound 예외 (Chris Sells의 도구 XmlSerializerPreCompiler 설명) 에서 다른 방법에 대한 정보를 찾을 수 있습니다 .
답변
Martin Sherburn이 말했듯이 이것은 정상적인 동작입니다. XmlSerializer의 생성자는 먼저 형식의 직렬화를 위해 생성 된 클래스를 포함해야하는 [YourAssembly] .XmlSerializers.dll이라는 어셈블리를 찾으려고합니다. 이러한 DLL은 아직 생성되지 않았으므로 (기본적으로는 아님) FileNotFoundException이 발생합니다. 이 경우 XmlSerializer의 생성자는 해당 예외를 포착하고 DLL은 XmlSerializer의 생성자에 의해 런타임에 자동으로 생성됩니다 (이는 컴퓨터의 % temp % 디렉토리에 C # 소스 파일을 생성 한 다음 C # 컴파일러를 사용하여 컴파일하여 수행됨). 동일한 유형의 XmlSerializer를 추가로 구성하면 이미 생성 된 DLL 만 사용됩니다.
업데이트 : .NET 4.5부터는
XmlSerializer
구성 파일 설정 ( useLegacySerializerGeneration ) 을 설정하여 명시 적으로 강제하지 않는 한 런타임에 직렬 변환기 어셈블리를 만들기 위해 더 이상 코드 생성을 수행하거나 C # 컴파일러로 컴파일을 수행하지 않습니다 . 이 변경으로 인해 종속성이 제거되고csc.exe
시작 성능이 향상됩니다. 출처 : .NET Framework 4.5 추가 정보 , 섹션 1.3.8.1.
XmlSerializer의 생성자가 예외를 처리합니다. 아무것도 할 필요가 없습니다. ‘계속'(F5)을 클릭하여 프로그램을 계속 실행하면 모든 것이 정상입니다. 프로그램 실행을 중지하고 예외 도우미를 팝업으로 표시하는 예외로 인해 방해를 받으면 ‘사용자 정의’가 해제되었거나 ‘User- 처리되지 않은 ‘.
‘내 코드 만’을 활성화하려면 도구 >> 옵션 >> 디버깅 >> 일반 >> 내 코드 만 활성화로 이동하십시오. FileNotFound가 발생할 때 실행 중단을 끄려면 디버그 >> 예외 >> 찾기 >>로 이동하여 ‘FileNotFoundException’을 입력하고 >> System.IO.FileNotFoundException에서 ‘Thrown’확인란을 선택 취소하십시오.
답변
Visual Studio 프로젝트 속성 ( “빌드”페이지, 올바르게 기억하면)에는 “직렬화 어셈블리 생성”이라는 옵션이 있습니다. [MyType의 어셈블리 포함] 을 생성하는 프로젝트의 경우 켜십시오 .
답변
이에 대한 해결 방법이 있습니다. 당신이 사용하는 경우
XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];
그 예외를 피해야합니다. 이것은 나를 위해 일했습니다.
경고 : 여러 번 사용하지 마십시오. 메모리 누수가 발생합니다
이 방법을 사용 XmlSerializer
하여 같은 유형의 인스턴스를 두 번 이상 만들면 미친 것처럼 메모리가 누출됩니다 !
이는이 메소드가 XmlSerializer(type)
및 XmlSerializer(type, defaultNameSpace)
생성자를 제공 한 경우 내장 캐싱을 무시하기 때문입니다 (다른 모든 생성자도 캐시를 무시 함).
이 두 생성자를 통하지 않는 XmlSerializer를 만드는 방법을 사용하는 경우 고유 한 캐싱을 구현해야합니다. 그렇지 않으면 메모리가 출혈 될 수 있습니다.
답변
나는이 정확한 문제에 부딪 쳤고 언급 된 해결책으로 해결할 수 없었습니다.
그런 다음 마침내 해결책을 찾았습니다. 시리얼 라이저는 유형뿐만 아니라 중첩 유형도 필요로합니다. 이것을 변경 :
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
이에:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());
나를 위해 문제를 해결했습니다. 더 이상 예외 또는 아무것도 없습니다.
답변
내 솔루션은 직렬화기를 만들기 위해 바로 반영하는 것입니다. 이는 예외를 일으키는 이상한 파일로드를 무시합니다. 직렬화기를 캐싱하는 도우미 기능으로 이것을 패키지했습니다.
private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>();
public static XmlSerializer CreateDefaultXmlSerializer(Type type)
{
XmlSerializer serializer;
if (_xmlSerializerCache.TryGetValue(type, out serializer))
{
return serializer;
}
else
{
var importer = new XmlReflectionImporter();
var mapping = importer.ImportTypeMapping(type, null, null);
serializer = new XmlSerializer(mapping);
return _xmlSerializerCache[type] = serializer;
}
}
답변
예외를 피하려면 다음 두 가지를 수행해야합니다.
- 직렬화 된 클래스에 속성 추가 (액세스 권한이 있기를 바랍니다)
- sgen.exe를 사용하여 직렬화 파일 생성
클래스에 System.Xml.Serialization.XmlSerializerAssembly 특성을 추가하십시오. ‘MyAssembly’를 MyClass가있는 어셈블리 이름으로 바꾸십시오.
[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{
…
}
sgen.exe 유틸리티를 사용하여 직렬화 파일을 생성하고 클래스의 어셈블리와 함께 배포하십시오.
‘sgen.exe MyAssembly.dll’은 MyAssembly.XmlSerializers.dll 파일을 생성합니다
이 두 가지 변경 사항으로 인해 .net에서 어셈블리를 직접 찾을 수 있습니다. 확인하고 Visual Studio 2008의 .NET Framework 3.5에서 작동합니다.
