public static void DefinePassThroughConstructors( this TypeBuilder @this,
Func<ConstructorInfo,MethodAttributes?> baseConstructorfilter = null,
Func<ConstructorInfo, CustomAttributeData, bool> constructorAttributesFilter = null,
Func<ParameterInfo, CustomAttributeData, bool> parameterAttributesFilter = null )
{
Type baseType = @this.BaseType;
foreach( var baseCtor in baseType.GetConstructors( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) )
{
if( baseCtor.IsPrivate ) continue;
MethodAttributes? newCtorAttr = baseCtor.Attributes;
if( baseConstructorfilter != null && !(newCtorAttr = baseConstructorfilter( baseCtor )).HasValue ) continue;
var parameters = baseCtor.GetParameters();
if( parameters.Length == 0 ) @this.DefineDefaultConstructor( newCtorAttr.Value );
else
{
Type[] parameterTypes = ReflectionHelper.CreateParametersType( parameters );
// REVIEW: Type.EmptyTypes replaces GetRequiredCustomModifiers and GetOptionalCustomModifiers
Type[][] requiredCustomModifiers = parameters.Select( p => Type.EmptyTypes ).ToArray();
Type[][] optionalCustomModifiers = parameters.Select( p => Type.EmptyTypes ).ToArray();
var ctor = @this.DefineConstructor( newCtorAttr.Value, baseCtor.CallingConvention, parameterTypes, requiredCustomModifiers, optionalCustomModifiers );
for( var i = 0; i < parameters.Length; ++i )
{
ParameterInfo parameter = parameters[i];
ParameterBuilder pBuilder = ctor.DefineParameter( i + 1, parameter.Attributes, parameter.Name );
if( (parameter.Attributes & ParameterAttributes.HasDefault) != 0 )
{
pBuilder.SetConstant( parameter.DefaultValue );
}
if( parameterAttributesFilter != null )
{
ReflectionHelper.GenerateCustomAttributeBuilder( parameter.CustomAttributes, pBuilder.SetCustomAttribute, a => parameterAttributesFilter( parameter, a ) );
}
else
{
ReflectionHelper.GenerateCustomAttributeBuilder( parameter.CustomAttributes, pBuilder.SetCustomAttribute );
}
}
if( constructorAttributesFilter != null )
{
ReflectionHelper.GenerateCustomAttributeBuilder( baseCtor.CustomAttributes, ctor.SetCustomAttribute, a => constructorAttributesFilter( baseCtor, a ) );
}
else
{
ReflectionHelper.GenerateCustomAttributeBuilder( baseCtor.CustomAttributes, ctor.SetCustomAttribute );
}
var g = ctor.GetILGenerator();
g.RepushActualParameters( true, parameters.Length + 1 );
g.Emit( OpCodes.Call, baseCtor );
g.Emit( OpCodes.Ret );
}
}
}