Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / WPF

Reflection Studio - Part 1 - Introduction: Architecture and Design

Rate me:
Please Sign up or sign in to vote.
4.83/5 (23 votes)
22 Sep 2010GPL36 min read 59.9K   6.9K   111  
Reflection Studio is a "developer" application for assembly, database, performance, and code generation, written in C# under WPF 4.0.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil.Cil;
using Mono.Cecil;

namespace ReflectionStudio.Core.Project
{
	internal class BodyWorker
	{
		// Fields
		private readonly MethodBody m_Body;
		private readonly CilWorker m_CilWorker;
		private readonly IDictionary<Instruction, Instruction> m_FixupMap = new Dictionary<Instruction, Instruction>(10);
		private readonly IDictionary<OpCode, OpCode> m_OpCodeRemap = new Dictionary<OpCode, OpCode>(20);
		private readonly IList<Instruction> m_OriginalInstructions;

		// Methods
		public BodyWorker(MethodBody body)
		{
			this.m_Body = body;
			this.m_CilWorker = body.CilWorker;
			this.m_OriginalInstructions = new List<Instruction>(body.Instructions.Count);
			foreach (Instruction instruction in body.Instructions)
			{
				this.m_OriginalInstructions.Add(instruction);
			}
			this.InitOpCodeRemap();
		}

		public Instruction Append(Instruction ins)
		{
			this.m_CilWorker.Append(ins);
			return ins;
		}

		public Instruction AppendAfter(Instruction afterIns, Instruction ins)
		{
			this.m_CilWorker.InsertAfter(afterIns, ins);
			return ins;
		}

		public Instruction Create(OpCode opcode)
		{
			return this.m_CilWorker.Create(opcode);
		}

		//public Instruction Create(OpCode opcode, CallSite site)
		//{
		//    return this.m_CilWorker.Create(opcode, site);
		//}

		public Instruction Create(OpCode opcode, Instruction label)
		{
			return this.m_CilWorker.Create(opcode, label);
		}

		public Instruction Create(OpCode opcode, VariableDefinition var)
		{
			return this.m_CilWorker.Create(opcode, var);
		}

		public Instruction Create(OpCode opcode, FieldReference field)
		{
			return this.m_CilWorker.Create(opcode, field);
		}

		public Instruction Create(OpCode opcode, MethodReference method)
		{
			return this.m_CilWorker.Create(opcode, method);
		}

		public Instruction Create(OpCode opcode, ParameterDefinition param)
		{
			return this.m_CilWorker.Create(opcode, param);
		}

		public Instruction Create(OpCode opcode, TypeReference type)
		{
			return this.m_CilWorker.Create(opcode, type);
		}

		public Instruction Create(OpCode opcode, byte b)
		{
			return this.m_CilWorker.Create(opcode, b);
		}

		public Instruction Create(OpCode opcode, double d)
		{
			return this.m_CilWorker.Create(opcode, d);
		}

		public Instruction Create(OpCode opcode, int i)
		{
			return this.m_CilWorker.Create(opcode, i);
		}

		public Instruction Create(OpCode opcode, Instruction[] labels)
		{
			return this.m_CilWorker.Create(opcode, labels);
		}

		public Instruction Create(OpCode opcode, long l)
		{
			return this.m_CilWorker.Create(opcode, l);
		}

		public Instruction Create(OpCode opcode, sbyte b)
		{
			return this.m_CilWorker.Create(opcode, b);
		}

		public Instruction Create(OpCode opcode, float f)
		{
			return this.m_CilWorker.Create(opcode, f);
		}

		public Instruction Create(OpCode opcode, string str)
		{
			return this.m_CilWorker.Create(opcode, str);
		}

		public void Done()
		{
			this.PerformFixupMapping();
			this.PerformOpCodeRemapping();
			//this.m_Body.opOptimize();
		}

		private void InitOpCodeRemap()
		{
			this.m_OpCodeRemap[OpCodes.Br_S] = OpCodes.Br;
			this.m_OpCodeRemap[OpCodes.Brfalse_S] = OpCodes.Brfalse;
			this.m_OpCodeRemap[OpCodes.Brtrue_S] = OpCodes.Brtrue;
			this.m_OpCodeRemap[OpCodes.Beq_S] = OpCodes.Beq;
			this.m_OpCodeRemap[OpCodes.Bge_S] = OpCodes.Bge;
			this.m_OpCodeRemap[OpCodes.Bgt_S] = OpCodes.Bgt;
			this.m_OpCodeRemap[OpCodes.Ble_S] = OpCodes.Ble;
			this.m_OpCodeRemap[OpCodes.Blt_S] = OpCodes.Blt;
			this.m_OpCodeRemap[OpCodes.Bne_Un_S] = OpCodes.Bne_Un;
			this.m_OpCodeRemap[OpCodes.Bge_Un_S] = OpCodes.Bge_Un;
			this.m_OpCodeRemap[OpCodes.Bgt_Un_S] = OpCodes.Bgt_Un;
			this.m_OpCodeRemap[OpCodes.Ble_Un_S] = OpCodes.Ble_Un;
			this.m_OpCodeRemap[OpCodes.Blt_Un_S] = OpCodes.Blt_Un;
			this.m_OpCodeRemap[OpCodes.Leave_S] = OpCodes.Leave;
		}

		public Instruction InsertAt(Instruction atIns, Instruction ins)
		{
			this.m_CilWorker.InsertBefore(atIns, ins);
			this.m_FixupMap.Add(atIns, ins);
			return ins;
		}

		public Instruction InsertBefore(Instruction beforeIns, Instruction ins)
		{
			this.m_CilWorker.InsertBefore(beforeIns, ins);
			return ins;
		}

		private void PerformFixupMapping()
		{
			foreach (KeyValuePair<Instruction, Instruction> pair in this.m_FixupMap)
			{
				Instruction key = pair.Key;
				Instruction instruction2 = pair.Value;
				foreach (ExceptionHandler handler in this.m_Body.ExceptionHandlers)
				{
					if (handler.TryStart == key)
					{
						handler.TryStart = instruction2;
					}
					if (handler.TryEnd == key)
					{
						handler.TryEnd = instruction2;
					}
					if (handler.FilterStart == key)
					{
						handler.FilterStart = instruction2;
					}
					if (handler.FilterEnd == key)
					{
						handler.FilterEnd = instruction2;
					}
					if (handler.HandlerStart == key)
					{
						handler.HandlerStart = instruction2;
					}
					if (handler.HandlerEnd == key)
					{
						handler.HandlerEnd = instruction2;
					}
				}
				foreach (Scope scope in this.m_Body.Scopes)
				{
					if (scope.Start == key)
					{
						scope.Start = instruction2;
					}
					if (scope.End == key)
					{
						scope.End = instruction2;
					}
				}
				foreach (Instruction instruction3 in this.m_OriginalInstructions)
				{
					Instruction[] instructionArray;
					OperandType operandType = instruction3.OpCode.OperandType;
					if (operandType != OperandType.InlineBrTarget)
					{
						if (operandType == OperandType.InlineSwitch)
						{
							goto Label_0184;
						}
						if (operandType != OperandType.ShortInlineBrTarget)
						{
							continue;
						}
					}
					if (instruction3.Operand == key)
					{
						instruction3.Operand = instruction2;
					}
					continue;
				Label_0184:
					instructionArray = (Instruction[]) instruction3.Operand;
					for (int i = 0; i < instructionArray.Length; i++)
					{
						if (instructionArray[i] == key)
						{
							instructionArray[i] = instruction2;
						}
					}
				}
			}
		}

		private void PerformOpCodeRemapping()
		{
			foreach (Instruction instruction in this.m_OriginalInstructions)
			{
				if (this.m_OpCodeRemap.ContainsKey(instruction.OpCode))
				{
					instruction.OpCode = this.m_OpCodeRemap[instruction.OpCode];
				}
			}
		}

		public void RemapBodyOutside(Instruction ins)
		{
			this.m_FixupMap.Add(this.m_Body.Instructions.Outside, ins);
		}

		public void Remove(Instruction ins)
		{
			this.m_CilWorker.Remove(ins);
		}

		public Instruction Replace(Instruction oldIns, Instruction ins)
		{
			this.m_CilWorker.Replace(oldIns, ins);
			this.m_FixupMap.Add(oldIns, ins);
			return ins;
		}

		// Properties
		public IList<Instruction> OriginalInstructions
		{
			get
			{
				List<Instruction> list = new List<Instruction>(this.m_OriginalInstructions.Count);
				list.AddRange(this.m_OriginalInstructions);
				return list;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions