diff Source/Reflection/Emit/MethodBuilderHelper.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Reflection/Emit/MethodBuilderHelper.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Emit;
+using System.Reflection;
+
+namespace BLToolkit.Reflection.Emit
+{
+	/// <summary>
+	/// A wrapper around the <see cref="MethodBuilder"/> class.
+	/// </summary>
+	/// <include file="Examples.CS.xml" path='examples/emit[@name="Emit"]/*' />
+	/// <include file="Examples.VB.xml" path='examples/emit[@name="Emit"]/*' />
+	/// <seealso cref="System.Reflection.Emit.MethodBuilder">MethodBuilder Class</seealso>
+	public class MethodBuilderHelper : MethodBuilderBase
+	{
+		/// <summary>
+		/// Initializes a new instance of the <see cref="MethodBuilderHelper"/> class
+		/// with the specified parameters.
+		/// </summary>
+		/// <param name="typeBuilder">Associated <see cref="TypeBuilderHelper"/>.</param>
+		/// <param name="methodBuilder">A <see cref="MethodBuilder"/></param>
+		public MethodBuilderHelper(TypeBuilderHelper typeBuilder, MethodBuilder methodBuilder)
+			: base(typeBuilder)
+		{
+			if (methodBuilder == null) throw new ArgumentNullException("methodBuilder");
+
+			_methodBuilder = methodBuilder;
+
+			methodBuilder.SetCustomAttribute(Type.Assembly.BLToolkitAttribute);
+		}
+
+		/// <summary>
+		/// Sets a custom attribute using a custom attribute type.
+		/// </summary>
+		/// <param name="attributeType">Attribute type.</param>
+		public void SetCustomAttribute(Type attributeType)
+		{
+			if (attributeType == null) throw new ArgumentNullException("attributeType");
+
+			ConstructorInfo ci = attributeType.GetConstructor(System.Type.EmptyTypes);
+			CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(ci, new object[0]);
+
+			_methodBuilder.SetCustomAttribute(caBuilder);
+		}
+
+		/// <summary>
+		/// Sets a custom attribute using a custom attribute type
+		/// and named properties.
+		/// </summary>
+		/// <param name="attributeType">Attribute type.</param>
+		/// <param name="properties">Named properties of the custom attribute.</param>
+		/// <param name="propertyValues">Values for the named properties of the custom attribute.</param>
+		public void SetCustomAttribute(
+			Type           attributeType,
+			PropertyInfo[] properties,
+			object[]       propertyValues)
+		{
+			if (attributeType == null) throw new ArgumentNullException("attributeType");
+
+			ConstructorInfo ci = attributeType.GetConstructor(System.Type.EmptyTypes);
+			CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(
+				ci, new object[0], properties, propertyValues);
+
+			_methodBuilder.SetCustomAttribute(caBuilder);
+		}
+
+		/// <summary>
+		/// Sets a custom attribute using a custom attribute type
+		/// and named property.
+		/// </summary>
+		/// <param name="attributeType">Attribute type.</param>
+		/// <param name="propertyName">A named property of the custom attribute.</param>
+		/// <param name="propertyValue">Value for the named property of the custom attribute.</param>
+		public void SetCustomAttribute(
+			Type   attributeType,
+			string propertyName,
+			object propertyValue)
+		{
+			SetCustomAttribute(
+				attributeType,
+				new PropertyInfo[] { attributeType.GetProperty(propertyName) },
+				new object[] { propertyValue });
+		}
+
+		/// <summary>
+		/// Initializes a new instance of the <see cref="MethodBuilderHelper"/> class
+		/// with the specified parameters.
+		/// </summary>
+		/// <param name="typeBuilder">Associated <see cref="TypeBuilderHelper"/>.</param>
+		/// <param name="methodBuilder">A <see cref="MethodBuilder"/></param>
+		/// <param name="genericArguments">Generic arguments of the method.</param>
+		/// <param name="returnType">The return type of the method.</param>
+		/// <param name="parameterTypes">The types of the parameters of the method.</param>
+		internal MethodBuilderHelper(
+			TypeBuilderHelper  typeBuilder,
+			MethodBuilder      methodBuilder,
+			Type[]             genericArguments,
+			Type               returnType,
+			Type[]             parameterTypes
+			)
+			: base(typeBuilder)
+		{
+			if (methodBuilder    == null) throw new ArgumentNullException("methodBuilder");
+			if (genericArguments == null) throw new ArgumentNullException("genericArguments");
+
+			_methodBuilder = methodBuilder;
+
+			var genArgNames = genericArguments.Select(t => t.Name).ToArray();
+			var genParams   = methodBuilder.DefineGenericParameters(genArgNames);
+
+			// Copy parameter constraints.
+			//
+			List<Type> interfaceConstraints = null;
+
+			for (var i = 0; i < genParams.Length; i++)
+			{
+				genParams[i].SetGenericParameterAttributes(genericArguments[i].GenericParameterAttributes);
+
+				foreach (var constraint in genericArguments[i].GetGenericParameterConstraints())
+				{
+					if (constraint.IsClass)
+						genParams[i].SetBaseTypeConstraint(constraint);
+					else
+					{
+						if (interfaceConstraints == null)
+							interfaceConstraints = new List<Type>();
+						interfaceConstraints.Add(constraint);
+					}
+				}
+
+				if (interfaceConstraints != null && interfaceConstraints.Count != 0)
+				{
+					genParams[i].SetInterfaceConstraints(interfaceConstraints.ToArray());
+					interfaceConstraints.Clear();
+				}
+			}
+
+			// When a method contains a generic parameter we need to replace all
+			// generic types from methodInfoDeclaration with local ones.
+			//
+			for (var i = 0; i < parameterTypes.Length; i++)
+				parameterTypes[i] = TypeHelper.TranslateGenericParameters(parameterTypes[i], genParams);
+
+			methodBuilder.SetParameters(parameterTypes);
+			methodBuilder.SetReturnType(TypeHelper.TranslateGenericParameters(returnType, genParams));
+
+			// Once all generic stuff is done is it is safe to call SetCustomAttribute
+			//
+			methodBuilder.SetCustomAttribute(Type.Assembly.BLToolkitAttribute);
+		}
+
+		private readonly MethodBuilder _methodBuilder;
+		/// <summary>
+		/// Gets MethodBuilder.
+		/// </summary>
+		public MethodBuilder MethodBuilder
+		{
+			get { return _methodBuilder; }
+		}
+
+		/// <summary>
+		/// Converts the supplied <see cref="MethodBuilderHelper"/> to a <see cref="MethodBuilder"/>.
+		/// </summary>
+		/// <param name="methodBuilder">The <see cref="MethodBuilderHelper"/>.</param>
+		/// <returns>A <see cref="MethodBuilder"/>.</returns>
+		public static implicit operator MethodBuilder(MethodBuilderHelper methodBuilder)
+		{
+			if (methodBuilder == null) throw new ArgumentNullException("methodBuilder");
+
+			return methodBuilder.MethodBuilder;
+		}
+
+		private EmitHelper _emitter;
+		/// <summary>
+		/// Gets <see cref="EmitHelper"/>.
+		/// </summary>
+		public override EmitHelper Emitter
+		{
+			get
+			{
+				if (_emitter == null)
+					_emitter = new EmitHelper(this, _methodBuilder.GetILGenerator());
+
+				return _emitter;
+			}
+		}
+
+		private MethodInfo _overriddenMethod;
+		/// <summary>
+		/// Gets or sets the base type method overridden by this method, if any.
+		/// </summary>
+		public  MethodInfo  OverriddenMethod
+		{
+			get { return _overriddenMethod;  }
+			set { _overriddenMethod = value; }
+		}
+
+		/// <summary>
+		/// Returns the type that declares this method.
+		/// </summary>
+		public Type DeclaringType
+		{
+			get { return _methodBuilder.DeclaringType; }
+		}
+	}
+}