Click here to Skip to main content
15,896,512 members
Articles / Programming Languages / MSIL

Assembly Manipulation and C# / VB.NET Code Injection

Rate me:
Please Sign up or sign in to vote.
4.95/5 (200 votes)
26 Apr 2013MIT5 min read 927.4K   25K   486  
Reflexil is an assembly editor and runs as a plug-in for Reflector or JustDecompile. Reflexil is able to manipulate IL code and save the modified assemblies to disk. Reflexil also supports "on-the-fly" C#/VB.NET code injection.
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
//     <version>$Revision: 3630 $</version>
// </file>

using System;
using System.Collections.Generic;
using System.Text;

namespace ICSharpCode.SharpDevelop.Dom
{
	/// <summary>
	/// ConstructedReturnType is a reference to generic class that specifies the type parameters.
	/// When getting the Members, this return type modifies the lists in such a way that the
	/// <see cref="GenericReturnType"/>s are replaced with the return types in the type parameters
	/// collection.
	/// Example: List&lt;string&gt;
	/// </summary>
	public sealed class ConstructedReturnType : DecoratingReturnType
	{
		// Return types that should be substituted for the generic types
		// If a substitution is unknown (type could not be resolved), the list
		// contains a null entry.
		IList<IReturnType> typeArguments;
		IReturnType baseType;
		
		public IList<IReturnType> TypeArguments {
			get {
				return typeArguments;
			}
		}
		
		public ConstructedReturnType(IReturnType baseType, IList<IReturnType> typeArguments)
		{
			if (baseType == null)
				throw new ArgumentNullException("baseType");
			if (typeArguments == null)
				throw new ArgumentNullException("typeArguments");
			this.typeArguments = typeArguments;
			this.baseType = baseType;
		}
		
		public override T CastToDecoratingReturnType<T>()
		{
			if (typeof(T) == typeof(ConstructedReturnType)) {
				return (T)(object)this;
			} else {
				return null;
			}
		}
		
		public override bool Equals(IReturnType rt)
		{
			return rt != null
				&& rt.IsConstructedReturnType
				&& this.DotNetName == rt.DotNetName;
		}
		
		public override int GetHashCode()
		{
			return this.DotNetName.GetHashCode();
		}
		
		public override IReturnType GetDirectReturnType()
		{
			IReturnType newBaseType = baseType.GetDirectReturnType();
			IReturnType[] newTypeArguments = new IReturnType[typeArguments.Count];
			bool typeArgumentsChanged = false;
			for (int i = 0; i < typeArguments.Count; i++) {
				if (typeArguments[i] != null)
					newTypeArguments[i] = typeArguments[i].GetDirectReturnType();
				if (typeArguments[i] != newTypeArguments[i])
					typeArgumentsChanged = true;
			}
			if (baseType == newBaseType && !typeArgumentsChanged)
				return this;
			else
				return new ConstructedReturnType(newBaseType, newTypeArguments);
		}
		
		public override IReturnType BaseType {
			get {
				return baseType;
			}
		}
		
		public IReturnType UnboundType {
			get {
				return baseType;
			}
		}
		
		/// <summary>
		/// Gets if <paramref name="t"/> is/contains a generic return type referring to a class type parameter.
		/// </summary>
		bool CheckReturnType(IReturnType t)
		{
			if (t == null) {
				return false;
			}
			if (t.IsGenericReturnType) {
				return t.CastToGenericReturnType().TypeParameter.Method == null;
			} else if (t.IsArrayReturnType) {
				return CheckReturnType(t.CastToArrayReturnType().ArrayElementType);
			} else if (t.IsConstructedReturnType) {
				foreach (IReturnType para in t.CastToConstructedReturnType().TypeArguments) {
					if (CheckReturnType(para)) return true;
				}
				return false;
			} else {
				return false;
			}
		}
		
		bool CheckParameters(IList<IParameter> l)
		{
			foreach (IParameter p in l) {
				if (CheckReturnType(p.ReturnType)) return true;
			}
			return false;
		}
		
		public override string DotNetName {
			get {
				string baseName = baseType.DotNetName;
				int pos = baseName.LastIndexOf('`');
				StringBuilder b;
				if (pos < 0)
					b = new StringBuilder(baseName);
				else
					b = new StringBuilder(baseName, 0, pos, pos + 20);
				b.Append('{');
				for (int i = 0; i < typeArguments.Count; ++i) {
					if (i > 0) b.Append(',');
					if (typeArguments[i] != null) {
						b.Append(typeArguments[i].DotNetName);
					}
				}
				b.Append('}');
				return b.ToString();
			}
		}
		
		public static IReturnType TranslateType(IReturnType input, IList<IReturnType> typeParameters, bool convertForMethod)
		{
			if (input == null || typeParameters == null || typeParameters.Count == 0) {
				return input; // nothing to do when there are no type parameters specified
			}
			if (input.IsGenericReturnType) {
				GenericReturnType rt = input.CastToGenericReturnType();
				if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null)) {
					if (rt.TypeParameter.Index < typeParameters.Count) {
						IReturnType newType = typeParameters[rt.TypeParameter.Index];
						if (newType != null) {
							return newType;
						}
					}
				}
			} else if (input.IsArrayReturnType) {
				ArrayReturnType arInput = input.CastToArrayReturnType();
				IReturnType e = arInput.ArrayElementType;
				IReturnType t = TranslateType(e, typeParameters, convertForMethod);
				if (e != t && t != null)
					return new ArrayReturnType(arInput.ProjectContent, t, arInput.ArrayDimensions);
			} else if (input.IsConstructedReturnType) {
				ConstructedReturnType cinput = input.CastToConstructedReturnType();
				List<IReturnType> para = new List<IReturnType>(cinput.TypeArguments.Count);
				foreach (IReturnType argument in cinput.TypeArguments) {
					para.Add(TranslateType(argument, typeParameters, convertForMethod));
				}
				return new ConstructedReturnType(cinput.UnboundType, para);
			}
			return input;
		}
		
		IReturnType TranslateType(IReturnType input)
		{
			return TranslateType(input, typeArguments, false);
		}
		
		public override List<IMethod> GetMethods()
		{
			List<IMethod> l = baseType.GetMethods();
			for (int i = 0; i < l.Count; ++i) {
				if (CheckReturnType(l[i].ReturnType) || CheckParameters(l[i].Parameters)) {
					l[i] = (IMethod)l[i].CreateSpecializedMember();
					if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
						l[i].DeclaringTypeReference = this;
					}
					l[i].ReturnType = TranslateType(l[i].ReturnType);
					for (int j = 0; j < l[i].Parameters.Count; ++j) {
						l[i].Parameters[j].ReturnType = TranslateType(l[i].Parameters[j].ReturnType);
					}
				}
			}
			return l;
		}
		
		public override List<IProperty> GetProperties()
		{
			List<IProperty> l = baseType.GetProperties();
			for (int i = 0; i < l.Count; ++i) {
				if (CheckReturnType(l[i].ReturnType) || CheckParameters(l[i].Parameters)) {
					l[i] = (IProperty)l[i].CreateSpecializedMember();
					if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
						l[i].DeclaringTypeReference = this;
					}
					l[i].ReturnType = TranslateType(l[i].ReturnType);
					for (int j = 0; j < l[i].Parameters.Count; ++j) {
						l[i].Parameters[j].ReturnType = TranslateType(l[i].Parameters[j].ReturnType);
					}
				}
			}
			return l;
		}
		
		public override List<IField> GetFields()
		{
			List<IField> l = baseType.GetFields();
			for (int i = 0; i < l.Count; ++i) {
				if (CheckReturnType(l[i].ReturnType)) {
					l[i] = (IField)l[i].CreateSpecializedMember();
					if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
						l[i].DeclaringTypeReference = this;
					}
					l[i].ReturnType = TranslateType(l[i].ReturnType);
				}
			}
			return l;
		}
		
		public override List<IEvent> GetEvents()
		{
			List<IEvent> l = baseType.GetEvents();
			for (int i = 0; i < l.Count; ++i) {
				if (CheckReturnType(l[i].ReturnType)) {
					l[i] = (IEvent)l[i].CreateSpecializedMember();
					if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
						l[i].DeclaringTypeReference = this;
					}
					l[i].ReturnType = TranslateType(l[i].ReturnType);
				}
			}
			return l;
		}
		
		public override string ToString()
		{
			string r = "[ConstructedReturnType: ";
			r += baseType;
			r += "<";
			for (int i = 0; i < typeArguments.Count; i++) {
				if (i > 0) r += ",";
				if (typeArguments[i] != null) {
					r += typeArguments[i];
				}
			}
			return r + ">]";
		}
	}
}

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 MIT License


Written By
Software Developer (Senior) Microsoft
United States United States
Sebastien Lebreton is a Software Engineer at Microsoft.

He is particularly interested in optimization, reverse engineering and distributed objects technologies.

Comments and Discussions