2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="Compilation.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
2017-08-21 15:34:15 +00:00
// <owner current="true" primary="true">Microsoft</owner>
2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
namespace System.Xml.Serialization {
using System.Configuration ;
using System.Reflection ;
using System.Reflection.Emit ;
using System.Collections ;
using System.IO ;
using System ;
using System.Text ;
using System.Xml ;
using System.Threading ;
using System.Security ;
using System.Security.Permissions ;
using System.Security.Policy ;
using System.Xml.Serialization.Configuration ;
using System.Diagnostics ;
using System.CodeDom.Compiler ;
using System.Globalization ;
using System.Runtime.Versioning ;
using System.Diagnostics.CodeAnalysis ;
internal class TempAssembly {
internal const string GeneratedAssemblyNamespace = "Microsoft.Xml.Serialization.GeneratedAssembly" ;
Assembly assembly ;
bool pregeneratedAssmbly = false ;
XmlSerializerImplementation contract = null ;
Hashtable writerMethods ;
Hashtable readerMethods ;
TempMethodDictionary methods ;
static object [ ] emptyObjectArray = new object [ 0 ] ;
Hashtable assemblies = new Hashtable ( ) ;
static volatile FileIOPermission fileIOPermission ;
internal class TempMethod {
internal MethodInfo writeMethod ;
internal MethodInfo readMethod ;
internal string name ;
internal string ns ;
internal bool isSoap ;
internal string methodKey ;
}
private TempAssembly ( ) {
}
internal TempAssembly ( XmlMapping [ ] xmlMappings , Type [ ] types , string defaultNamespace , string location , Evidence evidence ) {
bool containsSoapMapping = false ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
xmlMappings [ i ] . CheckShallow ( ) ;
if ( xmlMappings [ i ] . IsSoap ) {
containsSoapMapping = true ;
}
}
// We will make best effort to use RefEmit for assembly generation
bool fallbackToCSharpAssemblyGeneration = false ;
if ( ! containsSoapMapping & & ! TempAssembly . UseLegacySerializerGeneration ) {
try {
assembly = GenerateRefEmitAssembly ( xmlMappings , types , defaultNamespace , evidence ) ;
}
// Only catch and handle known failures with RefEmit
catch ( CodeGeneratorConversionException ) {
fallbackToCSharpAssemblyGeneration = true ;
}
// Add other known exceptions here...
//
}
else {
fallbackToCSharpAssemblyGeneration = true ;
}
if ( fallbackToCSharpAssemblyGeneration ) {
assembly = GenerateAssembly ( xmlMappings , types , defaultNamespace , evidence , XmlSerializerCompilerParameters . Create ( location ) , null , assemblies ) ;
}
#if DEBUG
// use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
if ( assembly = = null ) throw new InvalidOperationException ( Res . GetString ( Res . XmlInternalErrorDetails , "Failed to generate XmlSerializer assembly, but did not throw" ) ) ;
#endif
InitAssemblyMethods ( xmlMappings ) ;
}
internal TempAssembly ( XmlMapping [ ] xmlMappings , Assembly assembly , XmlSerializerImplementation contract ) {
this . assembly = assembly ;
InitAssemblyMethods ( xmlMappings ) ;
this . contract = contract ;
pregeneratedAssmbly = true ;
}
internal static bool UseLegacySerializerGeneration {
get {
if ( AppSettings . UseLegacySerializerGeneration . HasValue ) {
// AppSetting will always win if specified
return ( bool ) AppSettings . UseLegacySerializerGeneration ;
}
else {
#if CONFIGURATION_DEP
XmlSerializerSection configSection = ConfigurationManager . GetSection ( ConfigurationStrings . XmlSerializerSectionPath ) as XmlSerializerSection ;
return configSection = = null ? false : configSection . UseLegacySerializerGeneration ;
#else
return false ;
#endif
}
}
}
internal TempAssembly ( XmlSerializerImplementation contract ) {
this . contract = contract ;
pregeneratedAssmbly = true ;
}
internal XmlSerializerImplementation Contract {
get {
if ( contract = = null ) {
contract = ( XmlSerializerImplementation ) Activator . CreateInstance ( GetTypeFromAssembly ( this . assembly , "XmlSerializerContract" ) ) ;
}
return contract ;
}
}
internal void InitAssemblyMethods ( XmlMapping [ ] xmlMappings ) {
methods = new TempMethodDictionary ( ) ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
TempMethod method = new TempMethod ( ) ;
method . isSoap = xmlMappings [ i ] . IsSoap ;
method . methodKey = xmlMappings [ i ] . Key ;
XmlTypeMapping xmlTypeMapping = xmlMappings [ i ] as XmlTypeMapping ;
if ( xmlTypeMapping ! = null ) {
method . name = xmlTypeMapping . ElementName ;
method . ns = xmlTypeMapping . Namespace ;
}
methods . Add ( xmlMappings [ i ] . Key , method ) ;
}
}
/// <devdoc>
/// <para>
/// Attempts to load pre-generated serialization assembly.
/// First check for the [XmlSerializerAssembly] attribute
/// </para>
/// </devdoc>
// SxS: This method does not take any resource name and does not expose any resources to the caller.
// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
internal static Assembly LoadGeneratedAssembly ( Type type , string defaultNamespace , out XmlSerializerImplementation contract ) {
Assembly serializer = null ;
contract = null ;
string serializerName = null ;
// Packaged apps do not support loading generated serializers.
if ( Microsoft . Win32 . UnsafeNativeMethods . IsPackagedProcess . Value ) {
return null ;
}
bool logEnabled = DiagnosticsSwitches . PregenEventLog . Enabled ;
// check to see if we loading explicit pre-generated assembly
object [ ] attrs = type . GetCustomAttributes ( typeof ( XmlSerializerAssemblyAttribute ) , false ) ;
if ( attrs . Length = = 0 ) {
// Guess serializer name: if parent assembly signed use strong name
AssemblyName name = GetName ( type . Assembly , true ) ;
serializerName = Compiler . GetTempAssemblyName ( name , defaultNamespace ) ;
// use strong name
name . Name = serializerName ;
name . CodeBase = null ;
name . CultureInfo = CultureInfo . InvariantCulture ;
try {
serializer = Assembly . Load ( name ) ;
}
catch ( Exception e ) {
if ( e is ThreadAbortException | | e is StackOverflowException | | e is OutOfMemoryException ) {
throw ;
}
if ( logEnabled ) {
Log ( e . Message , EventLogEntryType . Information ) ;
}
byte [ ] token = name . GetPublicKeyToken ( ) ;
if ( token ! = null & & token . Length > 0 ) {
// the parent assembly was signed, so do not try to LoadWithPartialName
return null ;
}
#pragma warning disable 618
serializer = Assembly . LoadWithPartialName ( serializerName , null ) ;
#pragma warning restore 618
}
if ( serializer = = null ) {
#if ! FEATURE_PAL // EventLog
if ( logEnabled ) {
Log ( Res . GetString ( Res . XmlPregenCannotLoad , serializerName ) , EventLogEntryType . Information ) ;
}
#endif //!FEATURE_PAL // EventLog
return null ;
}
if ( ! IsSerializerVersionMatch ( serializer , type , defaultNamespace , null ) ) {
#if ! FEATURE_PAL // EventLog
if ( logEnabled )
Log ( Res . GetString ( Res . XmlSerializerExpiredDetails , serializerName , type . FullName ) , EventLogEntryType . Error ) ;
#endif //!FEATURE_PAL // EventLog
return null ;
}
}
else {
XmlSerializerAssemblyAttribute assemblyAttribute = ( XmlSerializerAssemblyAttribute ) attrs [ 0 ] ;
if ( assemblyAttribute . AssemblyName ! = null & & assemblyAttribute . CodeBase ! = null )
throw new InvalidOperationException ( Res . GetString ( Res . XmlPregenInvalidXmlSerializerAssemblyAttribute , "AssemblyName" , "CodeBase" ) ) ;
// found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer
if ( assemblyAttribute . AssemblyName ! = null ) {
serializerName = assemblyAttribute . AssemblyName ;
#pragma warning disable 618
serializer = Assembly . LoadWithPartialName ( serializerName , null ) ;
#pragma warning restore 618
}
else if ( assemblyAttribute . CodeBase ! = null & & assemblyAttribute . CodeBase . Length > 0 ) {
serializerName = assemblyAttribute . CodeBase ;
serializer = Assembly . LoadFrom ( serializerName ) ;
}
else {
serializerName = type . Assembly . FullName ;
serializer = type . Assembly ;
}
if ( serializer = = null ) {
throw new FileNotFoundException ( null , serializerName ) ;
}
}
Type contractType = GetTypeFromAssembly ( serializer , "XmlSerializerContract" ) ;
contract = ( XmlSerializerImplementation ) Activator . CreateInstance ( contractType ) ;
if ( contract . CanSerialize ( type ) )
return serializer ;
#if ! FEATURE_PAL // EventLog
if ( logEnabled )
Log ( Res . GetString ( Res . XmlSerializerExpiredDetails , serializerName , type . FullName ) , EventLogEntryType . Error ) ;
#endif //!FEATURE_PAL // EventLog
return null ;
}
#if ! FEATURE_PAL // EventLog
static void Log ( string message , EventLogEntryType type ) {
new EventLogPermission ( PermissionState . Unrestricted ) . Assert ( ) ;
EventLog . WriteEntry ( "XmlSerializer" , message , type ) ;
}
#endif //!FEATURE_PAL // EventLog
static AssemblyName GetName ( Assembly assembly , bool copyName ) {
PermissionSet perms = new PermissionSet ( PermissionState . None ) ;
perms . AddPermission ( new FileIOPermission ( PermissionState . Unrestricted ) ) ;
perms . Assert ( ) ;
return assembly . GetName ( copyName ) ;
}
static bool IsSerializerVersionMatch ( Assembly serializer , Type type , string defaultNamespace , string location ) {
if ( serializer = = null )
return false ;
object [ ] attrs = serializer . GetCustomAttributes ( typeof ( XmlSerializerVersionAttribute ) , false ) ;
if ( attrs . Length ! = 1 )
return false ;
XmlSerializerVersionAttribute assemblyInfo = ( XmlSerializerVersionAttribute ) attrs [ 0 ] ;
// we found out dated pre-generate assembly
//
if ( assemblyInfo . ParentAssemblyId = = GenerateAssemblyId ( type ) & & assemblyInfo . Namespace = = defaultNamespace )
return true ;
return false ;
}
// SxS: This method does not take any resource name and does not expose any resources to the caller.
// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
static string GenerateAssemblyId ( Type type ) {
Module [ ] modules = type . Assembly . GetModules ( ) ;
ArrayList list = new ArrayList ( ) ;
for ( int i = 0 ; i < modules . Length ; i + + ) {
list . Add ( modules [ i ] . ModuleVersionId . ToString ( ) ) ;
}
list . Sort ( ) ;
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < list . Count ; i + + ) {
sb . Append ( list [ i ] . ToString ( ) ) ;
sb . Append ( "," ) ;
}
return sb . ToString ( ) ;
}
internal static Assembly GenerateAssembly ( XmlMapping [ ] xmlMappings , Type [ ] types , string defaultNamespace , Evidence evidence , XmlSerializerCompilerParameters parameters , Assembly assembly , Hashtable assemblies ) {
FileIOPermission . Assert ( ) ;
Compiler compiler = new Compiler ( ) ;
try {
Hashtable scopeTable = new Hashtable ( ) ;
foreach ( XmlMapping mapping in xmlMappings )
scopeTable [ mapping . Scope ] = mapping ;
TypeScope [ ] scopes = new TypeScope [ scopeTable . Keys . Count ] ;
scopeTable . Keys . CopyTo ( scopes , 0 ) ;
assemblies . Clear ( ) ;
Hashtable importedTypes = new Hashtable ( ) ;
foreach ( TypeScope scope in scopes ) {
foreach ( Type t in scope . Types ) {
compiler . AddImport ( t , importedTypes ) ;
Assembly a = t . Assembly ;
string name = a . FullName ;
if ( assemblies [ name ] ! = null )
continue ;
if ( ! a . GlobalAssemblyCache ) {
assemblies [ name ] = a ;
}
}
}
for ( int i = 0 ; i < types . Length ; i + + ) {
compiler . AddImport ( types [ i ] , importedTypes ) ;
}
compiler . AddImport ( typeof ( object ) . Assembly ) ;
compiler . AddImport ( typeof ( XmlSerializer ) . Assembly ) ;
IndentedWriter writer = new IndentedWriter ( compiler . Source , false ) ;
writer . WriteLine ( "#if _DYNAMIC_XMLSERIALIZER_COMPILATION" ) ;
writer . WriteLine ( "[assembly:System.Security.AllowPartiallyTrustedCallers()]" ) ;
writer . WriteLine ( "[assembly:System.Security.SecurityTransparent()]" ) ;
writer . WriteLine ( "[assembly:System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]" ) ;
writer . WriteLine ( "#endif" ) ;
// Add AssemblyVersion attribute to match parent accembly version
if ( types ! = null & & types . Length > 0 & & types [ 0 ] ! = null ) {
writer . WriteLine ( "[assembly:System.Reflection.AssemblyVersionAttribute(\"" + types [ 0 ] . Assembly . GetName ( ) . Version . ToString ( ) + "\")]" ) ;
}
if ( assembly ! = null & & types . Length > 0 ) {
for ( int i = 0 ; i < types . Length ; i + + ) {
Type type = types [ i ] ;
if ( type = = null )
continue ;
if ( DynamicAssemblies . IsTypeDynamic ( type ) ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlPregenTypeDynamic , types [ i ] . FullName ) ) ;
}
}
writer . Write ( "[assembly:" ) ;
writer . Write ( typeof ( XmlSerializerVersionAttribute ) . FullName ) ;
writer . Write ( "(" ) ;
writer . Write ( "ParentAssemblyId=" ) ;
ReflectionAwareCodeGen . WriteQuotedCSharpString ( writer , GenerateAssemblyId ( types [ 0 ] ) ) ;
writer . Write ( ", Version=" ) ;
ReflectionAwareCodeGen . WriteQuotedCSharpString ( writer , ThisAssembly . Version ) ;
if ( defaultNamespace ! = null ) {
writer . Write ( ", Namespace=" ) ;
ReflectionAwareCodeGen . WriteQuotedCSharpString ( writer , defaultNamespace ) ;
}
writer . WriteLine ( ")]" ) ;
}
CodeIdentifiers classes = new CodeIdentifiers ( ) ;
classes . AddUnique ( "XmlSerializationWriter" , "XmlSerializationWriter" ) ;
classes . AddUnique ( "XmlSerializationReader" , "XmlSerializationReader" ) ;
string suffix = null ;
if ( types ! = null & & types . Length = = 1 & & types [ 0 ] ! = null ) {
suffix = CodeIdentifier . MakeValid ( types [ 0 ] . Name ) ;
if ( types [ 0 ] . IsArray ) {
suffix + = "Array" ;
}
}
writer . WriteLine ( "namespace " + GeneratedAssemblyNamespace + " {" ) ;
writer . Indent + + ;
writer . WriteLine ( ) ;
string writerClass = "XmlSerializationWriter" + suffix ;
writerClass = classes . AddUnique ( writerClass , writerClass ) ;
XmlSerializationWriterCodeGen writerCodeGen = new XmlSerializationWriterCodeGen ( writer , scopes , "public" , writerClass ) ;
writerCodeGen . GenerateBegin ( ) ;
string [ ] writeMethodNames = new string [ xmlMappings . Length ] ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
writeMethodNames [ i ] = writerCodeGen . GenerateElement ( xmlMappings [ i ] ) ;
}
writerCodeGen . GenerateEnd ( ) ;
writer . WriteLine ( ) ;
string readerClass = "XmlSerializationReader" + suffix ;
readerClass = classes . AddUnique ( readerClass , readerClass ) ;
XmlSerializationReaderCodeGen readerCodeGen = new XmlSerializationReaderCodeGen ( writer , scopes , "public" , readerClass ) ;
readerCodeGen . GenerateBegin ( ) ;
string [ ] readMethodNames = new string [ xmlMappings . Length ] ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
readMethodNames [ i ] = readerCodeGen . GenerateElement ( xmlMappings [ i ] ) ;
}
readerCodeGen . GenerateEnd ( readMethodNames , xmlMappings , types ) ;
string baseSerializer = readerCodeGen . GenerateBaseSerializer ( "XmlSerializer1" , readerClass , writerClass , classes ) ;
Hashtable serializers = new Hashtable ( ) ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
if ( serializers [ xmlMappings [ i ] . Key ] = = null ) {
serializers [ xmlMappings [ i ] . Key ] = readerCodeGen . GenerateTypedSerializer ( readMethodNames [ i ] , writeMethodNames [ i ] , xmlMappings [ i ] , classes , baseSerializer , readerClass , writerClass ) ;
}
}
readerCodeGen . GenerateSerializerContract ( "XmlSerializerContract" , xmlMappings , types , readerClass , readMethodNames , writerClass , writeMethodNames , serializers ) ;
writer . Indent - - ;
writer . WriteLine ( "}" ) ;
return compiler . Compile ( assembly , defaultNamespace , parameters , evidence ) ;
}
finally {
compiler . Close ( ) ;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification="It is safe because the serialization assembly is generated by the framework code, not by the user.")]
internal static Assembly GenerateRefEmitAssembly ( XmlMapping [ ] xmlMappings , Type [ ] types , string defaultNamespace , Evidence evidence ) {
Hashtable scopeTable = new Hashtable ( ) ;
foreach ( XmlMapping mapping in xmlMappings )
scopeTable [ mapping . Scope ] = mapping ;
TypeScope [ ] scopes = new TypeScope [ scopeTable . Keys . Count ] ;
scopeTable . Keys . CopyTo ( scopes , 0 ) ;
string assemblyName = "Microsoft.GeneratedCode" ;
AssemblyBuilder assemblyBuilder = CodeGenerator . CreateAssemblyBuilder ( AppDomain . CurrentDomain , assemblyName ) ;
ConstructorInfo SecurityTransparentAttribute_ctor = typeof ( SecurityTransparentAttribute ) . GetConstructor (
CodeGenerator . InstanceBindingFlags ,
null ,
CodeGenerator . EmptyTypeArray ,
null
) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( SecurityTransparentAttribute_ctor , new Object [ 0 ] ) ) ;
ConstructorInfo AllowPartiallyTrustedCallersAttribute_ctor = typeof ( AllowPartiallyTrustedCallersAttribute ) . GetConstructor (
CodeGenerator . InstanceBindingFlags ,
null ,
CodeGenerator . EmptyTypeArray ,
null
) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( AllowPartiallyTrustedCallersAttribute_ctor , new Object [ 0 ] ) ) ;
ConstructorInfo SecurityRulesAttribute_ctor = typeof ( SecurityRulesAttribute ) . GetConstructor (
CodeGenerator . InstanceBindingFlags ,
null ,
new Type [ ] { typeof ( SecurityRuleSet ) } ,
null
) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( SecurityRulesAttribute_ctor , new Object [ ] { SecurityRuleSet . Level1 } ) ) ;
// Add AssemblyVersion attribute to match parent accembly version
if ( types ! = null & & types . Length > 0 & & types [ 0 ] ! = null ) {
ConstructorInfo AssemblyVersionAttribute_ctor = typeof ( AssemblyVersionAttribute ) . GetConstructor (
CodeGenerator . InstanceBindingFlags ,
null ,
new Type [ ] { typeof ( String ) } ,
null
) ;
FileIOPermission . Assert ( ) ;
string assemblyVersion = types [ 0 ] . Assembly . GetName ( ) . Version . ToString ( ) ;
FileIOPermission . RevertAssert ( ) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( AssemblyVersionAttribute_ctor , new Object [ ] { assemblyVersion } ) ) ;
}
CodeIdentifiers classes = new CodeIdentifiers ( ) ;
classes . AddUnique ( "XmlSerializationWriter" , "XmlSerializationWriter" ) ;
classes . AddUnique ( "XmlSerializationReader" , "XmlSerializationReader" ) ;
string suffix = null ;
if ( types ! = null & & types . Length = = 1 & & types [ 0 ] ! = null ) {
suffix = CodeIdentifier . MakeValid ( types [ 0 ] . Name ) ;
if ( types [ 0 ] . IsArray ) {
suffix + = "Array" ;
}
}
ModuleBuilder moduleBuilder = CodeGenerator . CreateModuleBuilder ( assemblyBuilder , assemblyName ) ;
string writerClass = "XmlSerializationWriter" + suffix ;
writerClass = classes . AddUnique ( writerClass , writerClass ) ;
XmlSerializationWriterILGen writerCodeGen = new XmlSerializationWriterILGen ( scopes , "public" , writerClass ) ;
writerCodeGen . ModuleBuilder = moduleBuilder ;
writerCodeGen . GenerateBegin ( ) ;
string [ ] writeMethodNames = new string [ xmlMappings . Length ] ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
writeMethodNames [ i ] = writerCodeGen . GenerateElement ( xmlMappings [ i ] ) ;
}
Type writerType = writerCodeGen . GenerateEnd ( ) ;
string readerClass = "XmlSerializationReader" + suffix ;
readerClass = classes . AddUnique ( readerClass , readerClass ) ;
XmlSerializationReaderILGen readerCodeGen = new XmlSerializationReaderILGen ( scopes , "public" , readerClass ) ;
readerCodeGen . ModuleBuilder = moduleBuilder ;
readerCodeGen . CreatedTypes . Add ( writerType . Name , writerType ) ;
readerCodeGen . GenerateBegin ( ) ;
string [ ] readMethodNames = new string [ xmlMappings . Length ] ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
readMethodNames [ i ] = readerCodeGen . GenerateElement ( xmlMappings [ i ] ) ;
}
readerCodeGen . GenerateEnd ( readMethodNames , xmlMappings , types ) ;
string baseSerializer = readerCodeGen . GenerateBaseSerializer ( "XmlSerializer1" , readerClass , writerClass , classes ) ;
Hashtable serializers = new Hashtable ( ) ;
for ( int i = 0 ; i < xmlMappings . Length ; i + + ) {
if ( serializers [ xmlMappings [ i ] . Key ] = = null ) {
serializers [ xmlMappings [ i ] . Key ] = readerCodeGen . GenerateTypedSerializer ( readMethodNames [ i ] , writeMethodNames [ i ] , xmlMappings [ i ] , classes , baseSerializer , readerClass , writerClass ) ;
}
}
readerCodeGen . GenerateSerializerContract ( "XmlSerializerContract" , xmlMappings , types , readerClass , readMethodNames , writerClass , writeMethodNames , serializers ) ;
if ( DiagnosticsSwitches . KeepTempFiles . Enabled ) {
FileIOPermission . Assert ( ) ;
assemblyBuilder . Save ( assemblyName + ".dll" ) ;
}
return writerType . Assembly ;
}
// SxS: This method does not take any resource name and does not expose any resources to the caller.
// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
static MethodInfo GetMethodFromType ( Type type , string methodName , Assembly assembly ) {
MethodInfo method = type . GetMethod ( methodName ) ;
if ( method ! = null )
return method ;
MissingMethodException missingMethod = new MissingMethodException ( type . FullName , methodName ) ;
if ( assembly ! = null ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlSerializerExpired , assembly . FullName , assembly . CodeBase ) , missingMethod ) ;
}
throw missingMethod ;
}
internal static Type GetTypeFromAssembly ( Assembly assembly , string typeName ) {
typeName = GeneratedAssemblyNamespace + "." + typeName ;
Type type = assembly . GetType ( typeName ) ;
if ( type = = null ) throw new InvalidOperationException ( Res . GetString ( Res . XmlMissingType , typeName , assembly . FullName ) ) ;
return type ;
}
internal bool CanRead ( XmlMapping mapping , XmlReader xmlReader ) {
if ( mapping = = null )
return false ;
if ( mapping . Accessor . Any ) {
return true ;
}
TempMethod method = methods [ mapping . Key ] ;
return xmlReader . IsStartElement ( method . name , method . ns ) ;
}
string ValidateEncodingStyle ( string encodingStyle , string methodKey ) {
if ( encodingStyle ! = null & & encodingStyle . Length > 0 ) {
if ( methods [ methodKey ] . isSoap ) {
if ( encodingStyle ! = Soap . Encoding & & encodingStyle ! = Soap12 . Encoding ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlInvalidEncoding3 , encodingStyle , Soap . Encoding , Soap12 . Encoding ) ) ;
}
}
else {
throw new InvalidOperationException ( Res . GetString ( Res . XmlInvalidEncodingNotEncoded1 , encodingStyle ) ) ;
}
}
else {
if ( methods [ methodKey ] . isSoap ) {
encodingStyle = Soap . Encoding ;
}
}
return encodingStyle ;
}
internal static FileIOPermission FileIOPermission {
get {
if ( fileIOPermission = = null )
fileIOPermission = new FileIOPermission ( PermissionState . Unrestricted ) ;
return fileIOPermission ;
}
}
internal object InvokeReader ( XmlMapping mapping , XmlReader xmlReader , XmlDeserializationEvents events , string encodingStyle ) {
XmlSerializationReader reader = null ;
try {
encodingStyle = ValidateEncodingStyle ( encodingStyle , mapping . Key ) ;
reader = Contract . Reader ;
reader . Init ( xmlReader , events , encodingStyle , this ) ;
if ( methods [ mapping . Key ] . readMethod = = null ) {
if ( readerMethods = = null ) {
readerMethods = Contract . ReadMethods ;
}
string methodName = ( string ) readerMethods [ mapping . Key ] ;
if ( methodName = = null ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlNotSerializable , mapping . Accessor . Name ) ) ;
}
methods [ mapping . Key ] . readMethod = GetMethodFromType ( reader . GetType ( ) , methodName , pregeneratedAssmbly ? this . assembly : null ) ;
}
return methods [ mapping . Key ] . readMethod . Invoke ( reader , emptyObjectArray ) ;
}
catch ( SecurityException e ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlNoPartialTrust ) , e ) ;
}
finally {
if ( reader ! = null )
reader . Dispose ( ) ;
}
}
internal void InvokeWriter ( XmlMapping mapping , XmlWriter xmlWriter , object o , XmlSerializerNamespaces namespaces , string encodingStyle , string id ) {
XmlSerializationWriter writer = null ;
try {
encodingStyle = ValidateEncodingStyle ( encodingStyle , mapping . Key ) ;
writer = Contract . Writer ;
writer . Init ( xmlWriter , namespaces , encodingStyle , id , this ) ;
if ( methods [ mapping . Key ] . writeMethod = = null ) {
if ( writerMethods = = null ) {
writerMethods = Contract . WriteMethods ;
}
string methodName = ( string ) writerMethods [ mapping . Key ] ;
if ( methodName = = null ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlNotSerializable , mapping . Accessor . Name ) ) ;
}
methods [ mapping . Key ] . writeMethod = GetMethodFromType ( writer . GetType ( ) , methodName , pregeneratedAssmbly ? assembly : null ) ;
}
methods [ mapping . Key ] . writeMethod . Invoke ( writer , new object [ ] { o } ) ;
}
catch ( SecurityException e ) {
throw new InvalidOperationException ( Res . GetString ( Res . XmlNoPartialTrust ) , e ) ;
}
finally {
if ( writer ! = null )
writer . Dispose ( ) ;
}
}
internal Assembly GetReferencedAssembly ( string name ) {
return assemblies ! = null & & name ! = null ? ( Assembly ) assemblies [ name ] : null ;
}
internal bool NeedAssembyResolve {
get { return assemblies ! = null & & assemblies . Count > 0 ; }
}
internal sealed class TempMethodDictionary : DictionaryBase {
internal TempMethod this [ string key ] {
get {
return ( TempMethod ) Dictionary [ key ] ;
}
}
internal void Add ( string key , TempMethod value ) {
Dictionary . Add ( key , value ) ;
}
}
}
sealed class XmlSerializerCompilerParameters {
bool needTempDirAccess ;
CompilerParameters parameters ;
XmlSerializerCompilerParameters ( CompilerParameters parameters , bool needTempDirAccess ) {
this . needTempDirAccess = needTempDirAccess ;
this . parameters = parameters ;
}
internal bool IsNeedTempDirAccess { get { return this . needTempDirAccess ; } }
internal CompilerParameters CodeDomParameters { get { return this . parameters ; } }
internal static XmlSerializerCompilerParameters Create ( string location ) {
CompilerParameters parameters = new CompilerParameters ( ) ;
parameters . GenerateInMemory = true ;
if ( string . IsNullOrEmpty ( location ) ) {
#if CONFIGURATION_DEP
XmlSerializerSection configSection = ConfigurationManager . GetSection ( ConfigurationStrings . XmlSerializerSectionPath ) as XmlSerializerSection ;
location = configSection = = null ? location : configSection . TempFilesLocation ;
#endif
// Trim leading and trailing white spaces (VSWhidbey 229873)
if ( ! string . IsNullOrEmpty ( location ) ) {
location = location . Trim ( ) ;
}
}
parameters . TempFiles = new TempFileCollection ( location ) ;
return new XmlSerializerCompilerParameters ( parameters , string . IsNullOrEmpty ( location ) ) ;
}
internal static XmlSerializerCompilerParameters Create ( CompilerParameters parameters , bool needTempDirAccess ) {
return new XmlSerializerCompilerParameters ( parameters , needTempDirAccess ) ;
}
}
class TempAssemblyCacheKey {
string ns ;
object type ;
internal TempAssemblyCacheKey ( string ns , object type ) {
this . type = type ;
this . ns = ns ;
}
public override bool Equals ( object o ) {
TempAssemblyCacheKey key = o as TempAssemblyCacheKey ;
if ( key = = null ) return false ;
return ( key . type = = this . type & & key . ns = = this . ns ) ;
}
public override int GetHashCode ( ) {
return ( ( ns ! = null ? ns . GetHashCode ( ) : 0 ) ^ ( type ! = null ? type . GetHashCode ( ) : 0 ) ) ;
}
}
internal class TempAssemblyCache {
Hashtable cache = new Hashtable ( ) ;
internal TempAssembly this [ string ns , object o ] {
get { return ( TempAssembly ) cache [ new TempAssemblyCacheKey ( ns , o ) ] ; }
}
internal void Add ( string ns , object o , TempAssembly assembly ) {
TempAssemblyCacheKey key = new TempAssemblyCacheKey ( ns , o ) ;
lock ( this ) {
if ( cache [ key ] = = assembly ) return ;
Hashtable clone = new Hashtable ( ) ;
foreach ( object k in cache . Keys ) {
clone . Add ( k , cache [ k ] ) ;
}
cache = clone ;
cache [ key ] = assembly ;
}
}
}
}