/// <summary> /// Implements Class#new feature. /// </summary> public void BuildObjectConstruction(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName) { Debug.Assert(!IsSingletonClass, "Cannot instantiate singletons"); Type type = GetUnderlyingSystemType(); RubyMemberInfo initializer = ResolveMethod(Symbols.Initialize, true).InvalidateSitesOnOverride(); RubyMethodInfo overriddenInitializer = initializer as RubyMethodInfo; // check the version of this class to ensure the initializer won't be changed without rebuilding the site: metaBuilder.AddCondition( Ast.Equal(Ast.Property(Ast.Constant(this), RubyModule.VersionProperty), Ast.Constant(this.Version)) ); // Initializer is overridden => initializer is invoked on an uninitialized instance. // Is user class (defined in Ruby code) => construct it as if it had initializer that calls super immediately // (we need to "inherit" factories/constructors from the base class (e.g. class S < String; self; end.new('foo')). if (overriddenInitializer != null || (_isRubyClass && _structInfo == null)) { metaBuilder.Result = MakeAllocatorCall(args, () => Ast.Constant(Name)); if (overriddenInitializer != null || (_isRubyClass && initializer != null && !initializer.IsEmpty)) { BuildOverriddenInitializerCall(metaBuilder, args, initializer); } } else if (type.IsSubclassOf(typeof(Delegate))) { metaBuilder.Result = MakeDelegateConstructorCall(type, args); } else { MethodBase[] constructionOverloads; bool includeSelf; if (_structInfo != null) { constructionOverloads = new MethodBase[] { Methods.CreateStructInstance }; includeSelf = true; } else if (_factories != null) { constructionOverloads = (MethodBase[])ReflectionUtils.GetMethodInfos(_factories); includeSelf = true; } else { constructionOverloads = type.GetConstructors(); if (constructionOverloads.Length == 0) { throw RubyExceptions.CreateTypeError(String.Format("allocator undefined for {0}", Name)); } includeSelf = false; } RubyMethodGroupInfo.BuildCallNoFlow(metaBuilder, args, methodName, constructionOverloads, includeSelf, false); RubyMethodGroupInfo.ApplyBlockFlowHandlingInternal(metaBuilder, args); } }