示例#1
0
        /// <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);
            }
        }