Exemple #1
0
        /// <summary>
        /// Builds delegate that creates uninitialized class instance for purposes of deserialization and reflection.
        /// </summary>
        static bool TryBuildCreateEmptyObjectFunc(PhpTypeInfo tinfo, out Func <Context, object> activator)
        {
            Debug.Assert(tinfo != null);

            activator = null;

            if (tinfo.IsInterface)
            {
                // cannot be instantiated
            }
            else if (tinfo.Type.IsAbstract)
            {
                // abstract class,
                // generate a non-abstract class that implements this one:

                var dummytype = EmitHelpers.CreatDefaultAbstractClassImplementation(tinfo.Type, out var ctor);
                activator = _ctx => ctor.Invoke(new object[] { _ctx });
            }
            else if (tinfo.IsTrait)
            {
                // trait class, can be instantiated using following (and the only) .ctor:
                // .ctor( Context, TSelf )

                if (tinfo.Type.IsGenericTypeDefinition)
                {
                    // trait class must be constructed first!
                    throw new NotSupportedException("Trait type is not constructed, cannot be created.");
                    // tinfo = tinfo.Type.MakeGenericType(typeof(object));
                }
                else
                {
                    foreach (var c in tinfo.Type.GetConstructors())
                    {
                        // there is only one .ctor:
                        var ps = c.GetParameters();
                        if (ps.Length == 2 && ps[0].IsContextParameter() && ps[1].ParameterType == typeof(object) && c.IsPublic)
                        {
                            activator = _ctx => c.Invoke(new[] { _ctx, new object(), });
                        }
                    }
                }
            }
            else
            {
                // regular instantiable class

                foreach (var c in tinfo.Type.DeclaredConstructors)
                {
                    if (c.IsStatic || c.IsPrivate || c.IsPhpHidden())
                    {
                        continue;
                    }

                    var ps = c.GetParameters();

                    switch (ps.Length)
                    {
                    // .ctor()
                    case 0:
                        activator = (_ctx) => c.Invoke(Array.Empty <object>());
                        break;

                    // .ctor(Context)
                    case 1 when ps[0].IsContextParameter():