Exemplo n.º 1
0
        public static void CreateNewInstance(MethodBuilder sink, DataInfo info, string classIdReader, bool pooled,
                                             string refInst, bool needCreateVar, bool wrapType = false)
        {
            // Some bullshit logic here
            // All of this because of value wrapper concept that should be reconsidered
            var t    = wrapType ? info.realType : info.type;
            var name = wrapType ? info.accessPrefix + info.baseAccess : info.access;

            string newExpr  = "";
            bool   needCast = false;

            if (t == typeof(string))
            {
                newExpr = "string.Empty";
            }
            else if (t.IsArray)
            {
                newExpr = $"Array.Empty<{t.RealName(true).Remove(t.RealName(true).Length - 2)}>()";
            }
            else if (t.CanBeAncestor() && info.cantBeAncestor == false)
            {
                needCast = true;
                if (CodeGenTools.Valid(refInst))
                {
                    string poolArg = "";
                    if (t.HasPool() && pooled)
                    {
                        poolArg = "pool";
                    }
                    newExpr = $"{refInst}.{PolymorphNewInstOfSameType}({poolArg})";
                }
                else
                {
                    if (CodeGenTools.Valid(classIdReader) == false)
                    {
                        if (t.IsAbstract)
                        {
                            return;
                        }
                        newExpr = NewInstExpr(t, pooled);
                    }
                    else
                    {
                        var staticTypeCreator = baseClassMap.GetOrDefault(t, t).RealName(true);
                        if (t.IsGenericParameter)
                        {
                            if (t.GetGenericParameterConstraints().TryFind(par => !par.IsInterface, out var hardPar))
                            {
                                staticTypeCreator = hardPar.RealName(true);
                            }
                            else
                            {
                                Error($"can't generate new instance construction for unknown type {t} in {info.carrierType}, constrain this type with some base class like DataNode");
                            }
                        }
                        newExpr = $"{staticTypeCreator}.{PolymorphInstanceFuncName}({classIdReader})";
                    }
                }
            }
            else
            {
createNormally:
                if (t.IsAbstract)
                {
                    Error($"Type {t} is abstract but required to have constructor during {sink.classBuilder.name} generation");
                    return;
                }
                newExpr = NewInstExpr(t, pooled, info.defaultValue);
            }

            sink.content($"{(needCreateVar ? "var " : "")}{name} = {(needCast ? $"({t.RealName(true)})" : "")}{newExpr};");
        }
Exemplo n.º 2
0
        public static void GeneralReadFrom(MethodBuilder sink, DataInfo info,
                                           Action <MethodBuilder, DataInfo> baseReadCall, string isNullReader, string classIdReader,
                                           string directReader, string refInst, string refIdReader, bool pooled, Func <Type, string> configIdReader = null, bool needCreateVar = false,
                                           bool useTempVarThenAssign = false, bool getDataNodeFromRootWithRefId = false)
        {
            var t         = info.type;
            var canBeNull = info.canBeNull && !t.IsValueType;

            var    originalInfo = info;
            string tempVar      = "__" + originalInfo.baseAccess.Replace("[", "").Replace("]", "");

            if (useTempVarThenAssign)
            {
                sink.content($"var {tempVar} = {originalInfo.access};");
                info = new DataInfo
                {
                    type       = originalInfo.type,
                    baseAccess = tempVar,
                };
            }

            var  name          = info.access;
            bool newInstCalled = false;

            if (needCreateVar)
            {
                sink.content($"{info.type.RealName(true)} {info.name} = default;");
            }

            if (t.IsImmutableValueType() || t.IsValueType && t.IsControllable() == false)
            {
                sink.content($"{name} = {directReader};");
                return;
            }
            else if (t.IsRef())
            {
                if (CodeGenTools.Valid(refIdReader))
                {
                    sink.content($"{info.access}.id = {refIdReader};");
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                if (canBeNull)
                {
                    sink.content($"if ({isNullReader}) {{");
                    sink.indent++;
                    SinkRemovePostProcess(sink, info, pooled);
                    sink.content($"{name} = null;");
                    sink.indent--;
                    sink.content($"}}");
                    sink.content($"else {{ ");
                    sink.indent++;
                }

                bool fromExternalSource = false;
                if (t.IsConfig() && info.insideConfigStorage == false)
                {
                    ConfigFromId(sink, info, configIdReader, false);
                    fromExternalSource = true;
                }
                else if (getDataNodeFromRootWithRefId && typeof(IReferencableFromDataRoot).IsAssignableFrom(t))
                {
                    sink.content($"{info.access} = ({info.type.RealName(true)})root.Recall({refIdReader});");
                    fromExternalSource = true;
                }
                else
                {
                    if (info.sureIsNull && !info.type.IsValueType)
                    {
                        CreateNewInstance(sink, info, classIdReader, pooled, refInst, false);
                        newInstCalled = true;
                    }
                    else
                    {
                        string createNewCondition = "";
                        if (canBeNull || info.CanBeNullAfterConstruction())
                        {
                            createNewCondition = $"{name} == null";
                        }

                        string classIdVarName = $"{name.Replace('[', '_').Replace(']', '_').Replace('.', '_')}ClassId";
                        if (t.CanBeAncestor() && info.cantBeAncestor == false)
                        {
                            sink.content($"var {classIdVarName} = {classIdReader};");
                            createNewCondition = AddOrCondition(createNewCondition,
                                                                $"{name}.{PolymorphClassIdGetter} != {classIdVarName}");
                        }
                        if (info.type.IsImmutableType() == false && CodeGenTools.Valid(createNewCondition))
                        {
                            sink.content($"if ({createNewCondition}) {{");
                            sink.indent++;
                            SinkRemovePostProcess(sink, info, pooled);
                            CreateNewInstance(sink, info, classIdVarName, pooled, refInst, false);
                            newInstCalled = true;
                            sink.indent--;
                            sink.content($"}}");
                        }
                    }
                }

                if (!fromExternalSource)
                {
                    baseReadCall(sink, info);
                }

                if (canBeNull)
                {
                    sink.indent--;
                    sink.content($"}}");
                }
            }

            if (useTempVarThenAssign)
            {
                sink.content($"{originalInfo.access} = {tempVar};");
            }
        }