4 using System.CodeDom.Compiler;
5 using System.Collections.Generic;
8 using System.Runtime.Remoting.Contexts;
9 using System.Security.Policy;
11 using System.Text.RegularExpressions;
14 using Mono.Cecil.Rocks;
15 using SiliconStudio.Core;
17 namespace SiliconStudio.AssemblyProcessor
24 public static CodeDomProvider codeDomProvider =
new Microsoft.CSharp.CSharpCodeProvider();
26 public static AssemblyDefinition
GenerateSerializationAssembly(
PlatformType platformType, BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly,
string serializationAssemblyLocation,
string signKeyFile = null)
29 var serializerGenerator =
new ComplexSerializerCodeGenerator(assemblyResolver, assembly);
32 RegisterDefaultSerializationProfile(assemblyResolver, assembly, serializerGenerator);
35 var serializerGeneratedCode = serializerGenerator.TransformText();
37 var compilerParameters =
new CompilerParameters();
38 compilerParameters.IncludeDebugInformation =
false;
39 compilerParameters.GenerateInMemory =
false;
40 compilerParameters.CompilerOptions =
"/nostdlib";
41 compilerParameters.TreatWarningsAsErrors =
false;
42 compilerParameters.TempFiles.KeepFiles =
false;
47 var skipWindows =
"Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null";
51 if (assembly.Name.HasPublicKey)
54 if (signKeyFile == null)
55 throw new InvalidOperationException(
"Generating serialization code for signed assembly, but no key was specified.");
57 var assemblyPath = Path.GetDirectoryName(assembly.MainModule.FullyQualifiedName);
58 if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned)
61 compilerParameters.CompilerOptions += string.Format(
" /keyfile:\"{0}\"", signKeyFile);
66 compilerParameters.CompilerOptions += string.Format(
" /delaysign+ /keyfile:\"{0}\"", signKeyFile);
70 var assemblyLocations =
new HashSet<string>();
71 foreach (var referencedAssemblyName
in assembly.MainModule.AssemblyReferences)
73 if (referencedAssemblyName.FullName != skipWindows)
75 if (assemblyLocations.Add(referencedAssemblyName.Name))
78 compilerParameters.ReferencedAssemblies.Add(assemblyResolver.Resolve(referencedAssemblyName).MainModule.FullyQualifiedName);
85 var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
86 compilerParameters.ReferencedAssemblies.Add(mscorlibAssembly.MainModule.FullyQualifiedName);
87 var collectionType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Dictionary<,>).FullName);
88 compilerParameters.ReferencedAssemblies.Add(collectionType.Module.FullyQualifiedName);
94 if (assemblyLocations.Add(
"System"))
96 compilerParameters.ReferencedAssemblies.Add(assemblyResolver.Resolve(
"System").MainModule.FullyQualifiedName);
98 if (assemblyLocations.Add(
"System.Reflection"))
100 compilerParameters.ReferencedAssemblies.Add(assemblyResolver.Resolve(
"System.Reflection").MainModule.FullyQualifiedName);
104 compilerParameters.ReferencedAssemblies.Add(assembly.MainModule.FullyQualifiedName);
105 assemblyLocations.Add(assembly.Name.Name);
108 if (!assemblyLocations.Contains(
"SiliconStudio.Core"))
110 compilerParameters.ReferencedAssemblies.Add(assemblyResolver.Resolve(
"SiliconStudio.Core").MainModule.FullyQualifiedName);
113 compilerParameters.OutputAssembly = serializationAssemblyLocation;
114 var compilerResults = codeDomProvider.CompileAssemblyFromSource(compilerParameters, serializerGeneratedCode);
116 if (compilerResults.Errors.HasErrors)
118 var errors =
new StringBuilder();
119 errors.AppendLine(string.Format(
"Serialization assembly compilation: {0} error(s)", compilerResults.Errors.Count));
120 foreach (var error
in compilerResults.Errors)
121 errors.AppendLine(error.ToString());
122 throw new InvalidOperationException(errors.ToString());
126 var merge =
new ILRepacking.ILRepack()
128 OutputFile = assembly.MainModule.FullyQualifiedName,
130 CopyAttributes =
true,
131 AllowMultipleAssemblyLevelAttributes =
true,
132 XmlDocumentation =
false,
134 PrimaryAssemblyDefinition = assembly,
140 merge.SetInputAssemblies(
new string[] { serializationAssemblyLocation });
144 merge.SetSearchDirectories(assemblyResolver.GetSearchDirectories());
148 if (assembly.Name.HasPublicKey)
150 merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey;
151 merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken;
152 merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey;
153 if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned)
154 merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned;
160 File.Delete(serializationAssemblyLocation);
162 var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation,
"pdb");
163 if (
File.Exists(serializationAssemblyPdbFilePath))
165 File.Delete(serializationAssemblyPdbFilePath);
173 return merge.TargetAssemblyDefinition;
176 private static void RegisterDefaultSerializationProfile(IAssemblyResolver assemblyResolver, AssemblyDefinition assembly, ComplexSerializerCodeGenerator generator)
178 var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
179 if (mscorlibAssembly == null)
181 Console.WriteLine(
"Missing mscorlib.dll from assembly {0}", assembly.FullName);
182 throw new InvalidOperationException(
"Missing mscorlib.dll from assembly");
185 var coreSerializationAssembly = assemblyResolver.Resolve(
"SiliconStudio.Core");
188 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(IList<>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.ListInterfaceSerializer`1")));
189 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(List<>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.ListSerializer`1")));
190 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(KeyValuePair<,>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.KeyValuePairSerializer`2")));
191 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(
IDictionary<,>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.DictionaryInterfaceSerializer`2")));
192 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(Dictionary<,>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.DictionarySerializer`2")));
193 generator.SerializerFactories.Add(
new CecilGenericSerializerFactory(typeof(Nullable<>), coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.NullableSerializer`1")));
194 generator.SerializerFactories.Add(
new CecilEnumSerializerFactory(coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.EnumSerializer`1")));
195 generator.SerializerFactories.Add(
new CecilArraySerializerFactory(coreSerializationAssembly.MainModule.GetTypeResolved(
"SiliconStudio.Core.Serialization.Serializers.ArraySerializer`1")));
198 for (
int i = 1; i <= 4; ++i)
200 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
201 string.Format(
"System.Tuple`{0}", i),
202 coreSerializationAssembly.MainModule.GetTypeResolved(
string.Format(
"SiliconStudio.Core.Serialization.Serializers.TupleSerializer`{0}", i))));
204 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
string.Format(
"SiliconStudio.Core.Serialization.Serializers.TupleSerializer`{0}", i)));
208 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.ArraySerializer`1"));
209 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.KeyValuePairSerializer`2"));
210 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.ListSerializer`1"));
211 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.ListInterfaceSerializer`1"));
212 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.NullableSerializer`1"));
213 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.DictionarySerializer`2",
214 mscorlibAssembly.MainModule.GetTypeResolved(typeof(KeyValuePair<,>).FullName)));
215 generator.SerializerDependencies.Add(
new CecilSerializerDependency(
"SiliconStudio.Core.Serialization.Serializers.DictionaryInterfaceSerializer`2",
216 mscorlibAssembly.MainModule.GetTypeResolved(typeof(KeyValuePair<,>).FullName)));
221 if (!Regex.IsMatch(assemblyLocation,
".dll|.exe", RegexOptions.IgnoreCase))
222 throw new InvalidOperationException();
224 return Regex.Replace(assemblyLocation,
".dll|.exe",
".Serializers.dll", RegexOptions.IgnoreCase);
227 private static bool CheckSerializationAssembly(
string assemblyLocation,
string serializationAssemblyLocation)
229 return (
File.Exists(serializationAssemblyLocation)
230 && File.GetLastWriteTimeUtc(serializationAssemblyLocation) >=
File.GetLastWriteTimeUtc(assemblyLocation));
PlatformType
Describes the platform operating system.
static string GenerateSerializationAssemblyLocation(string assemblyLocation)
Various helper functions to generate complex serializer.
static AssemblyDefinition GenerateSerializationAssembly(PlatformType platformType, BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile=null)