/// <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():