using System;
using System.Collections.Generic;
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;
string[] genArgNames = Array.ConvertAll<Type, string>(genericArguments, delegate (Type t)
{
return t.Name;
});
GenericTypeParameterBuilder[] genParams = methodBuilder.DefineGenericParameters(genArgNames);
// Copy parameter constraints.
//
List<Type> interfaceConstraints = null;
for (int i = 0; i < genParams.Length; i++)
{
genParams[i].SetGenericParameterAttributes(genericArguments[i].GenericParameterAttributes);
foreach (Type 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 (int 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; }
}
}
} |