/// <summary> /// Generates a parameters constructor that initializes the proxy /// state with <see cref = "StandardInterceptor" /> just to make it non-null. /// <para> /// This constructor is important to allow proxies to be XML serializable /// </para> /// </summary> protected void GenerateParameterlessConstructor(ClassEmitter emitter, Type baseClass, FieldReference interceptorField) { // Check if the type actually has a default constructor var defaultConstructor = baseClass.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); if (defaultConstructor == null) { defaultConstructor = baseClass.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); if (defaultConstructor == null || defaultConstructor.IsPrivate) { return; } } var constructor = emitter.CreateConstructor(); // initialize fields with an empty interceptor constructor.CodeBuilder.AddStatement(new AssignStatement(interceptorField, new NewArrayExpression(1, typeof(IInterceptor)))); constructor.CodeBuilder.AddStatement( new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor), new Type[0]))); // Invoke base constructor constructor.CodeBuilder.InvokeBaseConstructor(defaultConstructor); constructor.CodeBuilder.AddStatement(new ReturnStatement()); }
protected void GenerateConstructor(ClassEmitter emitter, ConstructorInfo baseConstructor, ProxyConstructorImplementation impl, params FieldReference[] fields) { if (impl == ProxyConstructorImplementation.SkipConstructor) return; ArgumentReference[] args; ParameterInfo[] baseConstructorParams = null; if (baseConstructor != null) { baseConstructorParams = baseConstructor.GetParameters(); } if (baseConstructorParams != null && baseConstructorParams.Length != 0) { args = new ArgumentReference[fields.Length + baseConstructorParams.Length]; var offset = fields.Length; for (var i = offset; i < offset + baseConstructorParams.Length; i++) { var paramInfo = baseConstructorParams[i - offset]; args[i] = new ArgumentReference(paramInfo.ParameterType, paramInfo.DefaultValue); } } else { args = new ArgumentReference[fields.Length]; } for (var i = 0; i < fields.Length; i++) { args[i] = new ArgumentReference(fields[i].Reference.FieldType); } var constructor = emitter.CreateConstructor(args); if (baseConstructorParams != null && baseConstructorParams.Length != 0) { var last = baseConstructorParams.Last(); if (last.ParameterType.IsArray && last.HasAttribute<ParamArrayAttribute>()) { var parameter = constructor.ConstructorBuilder.DefineParameter(args.Length, ParameterAttributes.None, last.Name); var builder = AttributeUtil.CreateBuilder<ParamArrayAttribute>(); parameter.SetCustomAttribute(builder); } } for (var i = 0; i < fields.Length; i++) { constructor.CodeBuilder.AddStatement(new AssignStatement(fields[i], args[i].ToExpression())); } // Invoke base constructor if (impl == ProxyConstructorImplementation.CallBase) { if (baseConstructor != null) { Debug.Assert(baseConstructorParams != null); var slice = new ArgumentReference[baseConstructorParams.Length]; Array.Copy(args, fields.Length, slice, 0, baseConstructorParams.Length); constructor.CodeBuilder.InvokeBaseConstructor(baseConstructor, slice); } else { constructor.CodeBuilder.InvokeBaseConstructor(); } } constructor.CodeBuilder.AddStatement(new ReturnStatement()); }