using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
namespace BLToolkit.Reflection.Emit
{
using TypeBuilder.Builders;
/// <summary>
/// A wrapper around the <see cref="TypeBuilder"/> 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.TypeBuilder">TypeBuilder Class</seealso>
public class TypeBuilderHelper
{
/// <summary>
/// Initializes a new instance of the <see cref="TypeBuilderHelper"/> class
/// with the specified parameters.
/// </summary>
/// <param name="assemblyBuilder">Associated <see cref="AssemblyBuilderHelper"/>.</param>
/// <param name="typeBuilder">A <see cref="TypeBuilder"/></param>
public TypeBuilderHelper(AssemblyBuilderHelper assemblyBuilder, System.Reflection.Emit.TypeBuilder typeBuilder)
{
if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder");
if (typeBuilder == null) throw new ArgumentNullException("typeBuilder");
_assembly = assemblyBuilder;
_typeBuilder = typeBuilder;
_typeBuilder.SetCustomAttribute(_assembly.BLToolkitAttribute);
}
private readonly AssemblyBuilderHelper _assembly;
/// <summary>
/// Gets associated <see cref="AssemblyBuilderHelper"/>.
/// </summary>
public AssemblyBuilderHelper Assembly
{
get { return _assembly; }
}
private readonly System.Reflection.Emit.TypeBuilder _typeBuilder;
/// <summary>
/// Gets <see cref="System.Reflection.Emit.TypeBuilder"/>.
/// </summary>
public System.Reflection.Emit.TypeBuilder TypeBuilder
{
get { return _typeBuilder; }
}
/// <summary>
/// Converts the supplied <see cref="TypeBuilderHelper"/> to a <see cref="TypeBuilder"/>.
/// </summary>
/// <param name="typeBuilder">The <see cref="TypeBuilderHelper"/>.</param>
/// <returns>A <see cref="TypeBuilder"/>.</returns>
public static implicit operator System.Reflection.Emit.TypeBuilder(TypeBuilderHelper typeBuilder)
{
if (typeBuilder == null) throw new ArgumentNullException("typeBuilder");
return typeBuilder.TypeBuilder;
}
#region DefineMethod Overrides
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes 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>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(
string name, MethodAttributes attributes, Type returnType, params Type[] parameterTypes)
{
return new MethodBuilderHelper(this, _typeBuilder.DefineMethod(name, attributes, returnType, parameterTypes));
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes of the method. </param>
/// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> 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>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(
string name,
MethodAttributes attributes,
CallingConventions callingConvention,
Type returnType,
Type[] parameterTypes)
{
return new MethodBuilderHelper(this, _typeBuilder.DefineMethod(
name, attributes, callingConvention, returnType, parameterTypes));
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes of the method. </param>
/// <param name="returnType">The return type of the method.</param>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(string name, MethodAttributes attributes, Type returnType)
{
return new MethodBuilderHelper(
this,
_typeBuilder.DefineMethod(name, attributes, returnType, Type.EmptyTypes));
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes of the method. </param>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(string name, MethodAttributes attributes)
{
return new MethodBuilderHelper(
this,
_typeBuilder.DefineMethod(name, attributes, typeof(void), Type.EmptyTypes));
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes of the method. </param>
/// <returns>The defined method.</returns>
/// <param name="callingConvention">The calling convention of the method.</param>
public MethodBuilderHelper DefineMethod(
string name,
MethodAttributes attributes,
CallingConventions callingConvention)
{
return new MethodBuilderHelper(
this,
_typeBuilder.DefineMethod(name, attributes, callingConvention));
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="attributes">The attributes of the method. </param>
/// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> of the method.</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>
/// <returns>The defined generic method.</returns>
public MethodBuilderHelper DefineGenericMethod(
string name,
MethodAttributes attributes,
CallingConventions callingConvention,
Type[] genericArguments,
Type returnType,
Type[] parameterTypes)
{
return new MethodBuilderHelper(
this,
_typeBuilder.DefineMethod(name, attributes, callingConvention), genericArguments, returnType, parameterTypes);
}
private Dictionary<MethodInfo, MethodBuilder> _overriddenMethods;
/// <summary>
/// Retrieves the map of base type methods overridden by this type.
/// </summary>
public Dictionary<MethodInfo, MethodBuilder> OverriddenMethods
{
get { return _overriddenMethods ?? (_overriddenMethods = new Dictionary<MethodInfo,MethodBuilder>()); }
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
/// <param name="attributes">The attributes of the method. </param>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(
string name,
MethodInfo methodInfoDeclaration,
MethodAttributes attributes)
{
if (methodInfoDeclaration == null) throw new ArgumentNullException("methodInfoDeclaration");
MethodBuilderHelper method;
ParameterInfo[] pi = methodInfoDeclaration.GetParameters();
Type[] parameters = new Type[pi.Length];
for (int i = 0; i < pi.Length; i++)
parameters[i] = pi[i].ParameterType;
if (methodInfoDeclaration.ContainsGenericParameters)
{
method = DefineGenericMethod(
name,
attributes,
methodInfoDeclaration.CallingConvention,
methodInfoDeclaration.GetGenericArguments(),
methodInfoDeclaration.ReturnType,
parameters);
}
else
{
method = DefineMethod(
name,
attributes,
methodInfoDeclaration.CallingConvention,
methodInfoDeclaration.ReturnType,
parameters);
}
// Compiler overrides methods only for interfaces. We do the same.
// If we wanted to override virtual methods, then methods should've had
// MethodAttributes.VtableLayoutMask attribute
// and the following condition should've been used below:
// if ((methodInfoDeclaration is FakeMethodInfo) == false)
//
if (methodInfoDeclaration.DeclaringType.IsInterface && !(methodInfoDeclaration is FakeMethodInfo))
{
OverriddenMethods.Add(methodInfoDeclaration, method.MethodBuilder);
_typeBuilder.DefineMethodOverride(method.MethodBuilder, methodInfoDeclaration);
}
method.OverriddenMethod = methodInfoDeclaration;
for (int i = 0; i < pi.Length; i++)
method.MethodBuilder.DefineParameter(i + 1, pi[i].Attributes, pi[i].Name);
return method;
}
/// <summary>
/// Adds a new method to the class, with the given name and method signature.
/// </summary>
/// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
/// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(string name, MethodInfo methodInfoDeclaration)
{
return DefineMethod(name, methodInfoDeclaration, MethodAttributes.Virtual);
}
/// <summary>
/// Adds a new private method to the class.
/// </summary>
/// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
/// <returns>The defined method.</returns>
public MethodBuilderHelper DefineMethod(MethodInfo methodInfoDeclaration)
{
if (methodInfoDeclaration == null) throw new ArgumentNullException("methodInfoDeclaration");
bool isInterface = methodInfoDeclaration.DeclaringType.IsInterface;
bool isFake = methodInfoDeclaration is FakeMethodInfo;
string name = isInterface && !isFake?
methodInfoDeclaration.DeclaringType.FullName + "." + methodInfoDeclaration.Name:
methodInfoDeclaration.Name;
MethodAttributes attributes =
MethodAttributes.Virtual |
MethodAttributes.HideBySig |
MethodAttributes.PrivateScope |
methodInfoDeclaration.Attributes & MethodAttributes.SpecialName;
if (isInterface && !isFake)
attributes |= MethodAttributes.Private;
else if ((attributes & MethodAttributes.SpecialName) != 0)
attributes |= MethodAttributes.Public;
else
attributes |= methodInfoDeclaration.Attributes &
(MethodAttributes.Public | MethodAttributes.Private);
return DefineMethod(name, methodInfoDeclaration, attributes);
}
#endregion
/// <summary>
/// Creates a Type object for the class.
/// </summary>
/// <returns>Returns the new Type object for this class.</returns>
public Type Create()
{
return TypeBuilder.CreateType();
}
/// <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(Type.EmptyTypes);
CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(ci, new object[0]);
_typeBuilder.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(Type.EmptyTypes);
CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(
ci, new object[0], properties, propertyValues);
_typeBuilder.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 } );
}
private ConstructorBuilderHelper _typeInitializer;
/// <summary>
/// Gets the initializer for this type.
/// </summary>
public ConstructorBuilderHelper TypeInitializer
{
get
{
if (_typeInitializer == null)
_typeInitializer = new ConstructorBuilderHelper(this, _typeBuilder.DefineTypeInitializer());
return _typeInitializer;
}
}
/// <summary>
/// Returns true if the initializer for this type has a body.
/// </summary>
public bool IsTypeInitializerDefined
{
get { return _typeInitializer != null; }
}
private ConstructorBuilderHelper _defaultConstructor;
/// <summary>
/// Gets the default constructor for this type.
/// </summary>
public ConstructorBuilderHelper DefaultConstructor
{
get
{
if (_defaultConstructor == null)
{
ConstructorBuilder builder = _typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes);
_defaultConstructor = new ConstructorBuilderHelper(this, builder);
}
return _defaultConstructor;
}
}
/// <summary>
/// Returns true if the default constructor for this type has a body.
/// </summary>
public bool IsDefaultConstructorDefined
{
get { return _defaultConstructor != null; }
}
private ConstructorBuilderHelper _initConstructor;
/// <summary>
/// Gets the init context constructor for this type.
/// </summary>
public ConstructorBuilderHelper InitConstructor
{
get
{
if (_initConstructor == null)
{
ConstructorBuilder builder = _typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
new Type[] { typeof(InitContext) });
_initConstructor = new ConstructorBuilderHelper(this, builder);
}
return _initConstructor;
}
}
/// <summary>
/// Returns true if a constructor with parameter of <see cref="InitContext"/> for this type has a body.
/// </summary>
public bool IsInitConstructorDefined
{
get { return _initConstructor != null; }
}
/// <summary>
/// Adds a new field to the class, with the given name, attributes and field type.
/// </summary>
/// <param name="fieldName">The name of the field. <paramref name="fieldName"/> cannot contain embedded nulls.</param>
/// <param name="type">The type of the field.</param>
/// <param name="attributes">The attributes of the field.</param>
/// <returns>The defined field.</returns>
public FieldBuilder DefineField(
string fieldName,
Type type,
FieldAttributes attributes)
{
return _typeBuilder.DefineField(fieldName, type, attributes);
}
#region DefineConstructor Overrides
/// <summary>
/// Adds a new public constructor to the class, with the given parameters.
/// </summary>
/// <param name="parameterTypes">The types of the parameters of the method.</param>
/// <returns>The defined constructor.</returns>
public ConstructorBuilderHelper DefinePublicConstructor(params Type[] parameterTypes)
{
return new ConstructorBuilderHelper(
this,
_typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard, parameterTypes));
}
/// <summary>
/// Adds a new constructor to the class, with the given attributes and parameters.
/// </summary>
/// <param name="attributes">The attributes of the field.</param>
/// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> of the method.</param>
/// <param name="parameterTypes">The types of the parameters of the method.</param>
/// <returns>The defined constructor.</returns>
public ConstructorBuilderHelper DefineConstructor(
MethodAttributes attributes,
CallingConventions callingConvention,
params Type[] parameterTypes)
{
return new ConstructorBuilderHelper(
this,
_typeBuilder.DefineConstructor(attributes, callingConvention, parameterTypes));
}
#endregion
#region DefineNestedType Overrides
/// <summary>
/// Defines a nested type given its name..
/// </summary>
/// <param name="name">The short name of the type.</param>
/// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
/// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string)">
/// TypeBuilder.DefineNestedType Method</seealso>
public TypeBuilderHelper DefineNestedType(string name)
{
return new TypeBuilderHelper(_assembly, _typeBuilder.DefineNestedType(name));
}
/// <summary>
/// Defines a public nested type given its name and the type that it extends.
/// </summary>
/// <param name="name">The short name of the type.</param>
/// <param name="parent">The type that the nested type extends.</param>
/// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
/// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type)">
/// TypeBuilder.DefineNestedType Method</seealso>
public TypeBuilderHelper DefineNestedType(string name, Type parent)
{
return new TypeBuilderHelper(
_assembly,
_typeBuilder.DefineNestedType(name, TypeAttributes.NestedPublic, parent));
}
/// <summary>
/// Defines a nested type given its name, attributes, and the type that it extends.
/// </summary>
/// <param name="name">The short name of the type.</param>
/// <param name="attributes">The attributes of the type.</param>
/// <param name="parent">The type that the nested type extends.</param>
/// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
/// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type)">
/// TypeBuilder.DefineNestedType Method</seealso>
public TypeBuilderHelper DefineNestedType(
string name,
TypeAttributes attributes,
Type parent)
{
return new TypeBuilderHelper(
_assembly,
_typeBuilder.DefineNestedType(name, attributes, parent));
}
/// <summary>
/// Defines a public nested type given its name, the type that it extends, and the interfaces that it implements.
/// </summary>
/// <param name="name">The short name of the type.</param>
/// <param name="parent">The type that the nested type extends.</param>
/// <param name="interfaces">The interfaces that the nested type implements.</param>
/// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
/// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type,Type[])">
/// TypeBuilder.DefineNestedType Method</seealso>
public TypeBuilderHelper DefineNestedType(
string name,
Type parent,
params Type[] interfaces)
{
return new TypeBuilderHelper(
_assembly,
_typeBuilder.DefineNestedType(name, TypeAttributes.NestedPublic, parent, interfaces));
}
/// <summary>
/// Defines a nested type given its name, attributes, the type that it extends, and the interfaces that it implements.
/// </summary>
/// <param name="name">The short name of the type.</param>
/// <param name="attributes">The attributes of the type.</param>
/// <param name="parent">The type that the nested type extends.</param>
/// <param name="interfaces">The interfaces that the nested type implements.</param>
/// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
/// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso>
public TypeBuilderHelper DefineNestedType(
string name,
TypeAttributes attributes,
Type parent,
params Type[] interfaces)
{
return new TypeBuilderHelper(
_assembly,
_typeBuilder.DefineNestedType(name, attributes, parent, interfaces));
}
#endregion
}
} |