2009-03-24 3 views
8

.NET에서 XmlSerializer 인스턴스를 만들 때 지정된 형식을 serialize하고 deserialize하기위한 어셈블리가 동적으로 생성됩니다. 이것은 시간이 많이 소요되는 과정입니다. Microsoft의 sgen.exe 도구를 사용하면 나중에 동적으로 생성하지 않고 XmlSerializer 인스턴스를 사전 컴파일하여 사용할 수 있습니다. 불행히도 XmlAttributeOverrides를 사용하는 XmlSerializer 인스턴스에서는이 작업을 수행 할 수 없습니다.XmlSerializer를 XmlAttributeOverrides로 미리 컴파일

런타임시 생성되지 않도록 이러한 XmlSerializer 인스턴스를 사전 컴파일하는 방법이 있습니까?

+0

어디에서 더 여기에 왔습니까? – Rory

답변

6

Andreas, 이것은 sgen 도구 자체의 문제는 아니며 XmlSerializer 구현 때문입니다.

형식 인수가 하나만있는 생성자를 사용하여 XmlSerializer의 인스턴스를 만들면 캐시를 검사하여 미리 생성 된 어셈블리를 찾습니다. 그러나 생성자를 XmlAttributeOverrides와 함께 사용하면 XmlSerializer는 캐시를 확인하지 않고 바로 temp 어셈블리를 생성합니다.

아마도 sgen과 같은 도구로 컴파일 타임에 "예견"할 수없는 XmlAttributeOverrides 인수를 사용하여 직렬화 논리가 상당히 변경 되었기 때문일 수 있습니다.

미리 컴파일 된 것이 필요한 경우 XmlAttributeOverrides를 피할 필요가 있습니다. 이것이 가능하지 않으면 필요한 XmlSerializer 인스턴스를 백그라운드 스레드에서 미리 만들어보십시오. 그냥 관심을

, 여기에 기본 생성자 코드입니다 (검사 캐시와 미리 생성 된 어셈블리를 찾습니다) :

public XmlSerializer(Type type, string defaultNamespace) 
{ 
    this.events = new XmlDeserializationEvents(); 
    if (type == null) 
    { 
     throw new ArgumentNullException("type"); 
    } 
    this.mapping = GetKnownMapping(type, defaultNamespace); 
    if (this.mapping != null) 
    { 
     this.primitiveType = type; 
    } 
    else 
    { 
     this.tempAssembly = cache[defaultNamespace, type]; 
     if (this.tempAssembly == null) 
     { 
      lock (cache) 
      { 
       this.tempAssembly = cache[defaultNamespace, type]; 
       if (this.tempAssembly == null) 
       { 
        XmlSerializerImplementation implementation; 
        Assembly assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out implementation); 
        if (assembly == null) 
        { 
         this.mapping = new XmlReflectionImporter(defaultNamespace).ImportTypeMapping(type, null, defaultNamespace); 
         this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace); 
        } 
        else 
        { 
         this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); 
         this.tempAssembly = new TempAssembly(new XmlMapping[] { this.mapping }, assembly, implementation); 
        } 
       } 
       cache.Add(defaultNamespace, type, this.tempAssembly); 
      } 
     } 
     if (this.mapping == null) 
     { 
      this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); 
     } 
    } 
} 

을 그리고 여기 XmlAttributeOverrides (항상 직렬화를 생성에 사용되는 생성자 어셈블리) :

public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location, Evidence evidence) 
{ 
    this.events = new XmlDeserializationEvents(); 
    if (type == null) 
    { 
     throw new ArgumentNullException("type"); 
    } 
    XmlReflectionImporter importer = new XmlReflectionImporter(overrides, defaultNamespace); 
    for (int i = 0; i < extraTypes.Length; i++) 
    { 
     importer.IncludeType(extraTypes[i]); 
    } 
    this.mapping = importer.ImportTypeMapping(type, root, defaultNamespace); 
    if (location != null) 
    { 
     this.DemandForUserLocation(); 
    } 
    this.tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence); 
} 
+0

아,이 같은 문제가 발생했습니다. 불행히도 csc.exe (보호 모드 Internet Explorer에서 실행 중입니다)를 시작할 수 없기 때문에 일련 화 어셈블리의 동적 생성을 사용할 수 없습니다. 어떤 제안? XmlSerializer에 의해 생성 된 temp .cs 파일을 캡처하고이를 내 빌드에 포함시킨 다음 XmlSerializer 대신 직접 사용하는 것이 좋습니다. 지저분한 소리는 있지만 다른 아이디어는 없나요? 내 qn 여기 : http://stackoverflow.com/questions/7333689/generating-an-xml-serialization-assembly-for-a-custom-xmlserializer – Rory