4 using System.Collections.Generic;
7 using System.Runtime.CompilerServices;
11 using Mono.Cecil.Rocks;
14 namespace SiliconStudio.AssemblyProcessor
20 var assembly = context.Assembly;
21 var fields =
new List<FieldDefinition>();
23 var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly);
24 if (mscorlibAssembly == null)
25 throw new InvalidOperationException(
"Missing mscorlib.dll from assembly");
27 MethodDefinition parameterKeysMergeMethod = null;
28 TypeDefinition assemblyEffectKeysAttributeType = null;
29 var getTypeFromHandleMethod =
new Lazy<MethodReference>(() =>
32 var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(
Type).FullName);
33 return assembly.MainModule.Import(typeType.Methods.First(x => x.Name ==
"GetTypeFromHandle"));
36 var effectKeysStaticConstructors =
new List<MethodReference>();
38 foreach (var type
in assembly.MainModule.GetTypes())
42 foreach (var field
in type.Fields.Where(x => x.IsStatic))
44 var fieldBaseType = field.FieldType;
45 while (fieldBaseType != null)
47 if (fieldBaseType.FullName ==
"SiliconStudio.Paradox.Effects.ParameterKey")
50 var resolvedFieldBaseType = fieldBaseType.Resolve();
51 if (resolvedFieldBaseType == null)
57 fieldBaseType = resolvedFieldBaseType.BaseType;
60 if (fieldBaseType == null)
66 if (fields.Count == 0)
70 var cctor = type.GetStaticConstructor();
75 if (parameterKeysMergeMethod == null)
77 AssemblyDefinition paradoxEngineAssembly;
80 paradoxEngineAssembly = assembly.Name.Name ==
"SiliconStudio.Paradox"
82 : context.AssemblyResolver.Resolve(
"SiliconStudio.Paradox");
86 Console.WriteLine(
"Error, cannot find [SiliconStudio.Paradox] assembly for processing ParameterKeyProcessor");
91 var parameterKeysType = paradoxEngineAssembly.MainModule.GetTypes().First(x => x.Name ==
"ParameterKeys");
92 parameterKeysMergeMethod = parameterKeysType.Methods.First(x => x.Name ==
"Merge");
93 assemblyEffectKeysAttributeType = paradoxEngineAssembly.MainModule.GetTypes().First(x => x.Name ==
"AssemblyEffectKeysAttribute");
96 var cctorIL = cctor.Body.GetILProcessor();
97 var cctorInstructions = cctor.Body.Instructions;
99 var keyClassName = type.Name;
100 if (keyClassName.EndsWith(
"Keys"))
101 keyClassName = keyClassName.Substring(0, keyClassName.Length - 4);
105 bool cctorModified =
false;
108 for (
int i = 0; i < cctorInstructions.Count; ++i)
110 var fieldInstruction = cctorInstructions[i];
112 if (fieldInstruction.OpCode == OpCodes.Stsfld
113 && fields.Contains(fieldInstruction.Operand))
115 var activeField = (FieldReference)fieldInstruction.Operand;
117 var nextInstruction = cctorInstructions[i + 1];
118 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldsfld, activeField));
119 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldtoken, type));
120 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
121 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Ldstr, keyClassName + activeField.Name));
122 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Call, assembly.MainModule.Import(parameterKeysMergeMethod)));
123 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Castclass, activeField.FieldType));
124 cctorIL.InsertBefore(nextInstruction, Instruction.Create(OpCodes.Stsfld, activeField));
125 i = cctorInstructions.IndexOf(nextInstruction);
126 cctorModified =
true;
132 effectKeysStaticConstructors.Add(cctor);
136 if (effectKeysStaticConstructors.Count > 0)
139 assembly.CustomAttributes.Add(
new CustomAttribute(assembly.MainModule.Import(assemblyEffectKeysAttributeType.GetConstructors().First(x => !x.HasParameters))));
142 var voidType = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetTypeResolved(typeof(
void).FullName));
143 var moduleClass = assembly.MainModule.Types.First(t => t.Name ==
"<Module>");
144 var staticConstructor = moduleClass.GetStaticConstructor();
145 if (staticConstructor == null)
147 staticConstructor =
new MethodDefinition(
".cctor",
150 staticConstructor.Body.GetILProcessor().Append(Instruction.Create(OpCodes.Ret));
152 moduleClass.Methods.Add(staticConstructor);
155 var il = staticConstructor.Body.GetILProcessor();
157 var returnInstruction = staticConstructor.Body.Instructions.Last();
158 var newReturnInstruction = Instruction.Create(returnInstruction.OpCode);
159 newReturnInstruction.Operand = returnInstruction.Operand;
161 returnInstruction.OpCode = OpCodes.Nop;
162 returnInstruction.Operand = null;
164 var typeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(
Type).FullName);
165 var typeHandleProperty = typeType.Properties.First(x => x.Name ==
"TypeHandle");
166 var getTypeHandleMethod = assembly.MainModule.Import(typeHandleProperty.GetMethod);
168 var runtimeHelpersType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(RuntimeHelpers).FullName);
169 var runClassConstructorMethod = assembly.MainModule.Import(runtimeHelpersType.Methods.Single(x => x.IsPublic && x.Name ==
"RunClassConstructor" && x.Parameters.Count == 1 && x.Parameters[0].ParameterType.FullName == typeof(RuntimeTypeHandle).FullName));
172 staticConstructor.Body.SimplifyMacros();
173 foreach (var effectKeysStaticConstructor
in effectKeysStaticConstructors)
175 il.Append(Instruction.Create(OpCodes.Ldtoken, effectKeysStaticConstructor.DeclaringType));
176 il.Append(Instruction.Create(OpCodes.Call, getTypeFromHandleMethod.Value));
177 il.Append(Instruction.Create(OpCodes.Callvirt, getTypeHandleMethod));
178 il.Append(Instruction.Create(OpCodes.Call, runClassConstructorMethod));
180 il.Append(newReturnInstruction);
181 staticConstructor.Body.OptimizeMacros();
Mono.Cecil.MethodAttributes MethodAttributes
Mono.Cecil.MethodAttributes MethodAttributes
bool Process(AssemblyProcessorContext context)
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.