Esempio n. 1
0
        public static void GenUpdateFrom(Type type, bool pooled, string funcPrefix = "")
        {
            const string instanceCastedName = "otherConcrete";
            const string instanceName       = "other";

            string otherName = instanceName;
            var    flag      = pooled ? GenTaskFlags.PooledUpdateFrom : GenTaskFlags.UpdateFrom;

            var updateFromType = type.TopParentImplementingFlag(flag) ?? type;

            MethodBuilder sink = MakeGenMethod(type, flag, funcPrefix + UpdateFuncName, typeof(void),
                                               $"{updateFromType.RealName(true)} {instanceName}{(pooled ? ", ObjectPool pool" : "")}");


            if (type.IsList())
            {
                // For livable list that we do not need to generate in not constructed form
                if (type.IsConstructedGenericType == false)
                {
                    return;
                }
                var elemType = type.GenericTypeArguments[0];
                SinkUpdateFromList(sink, elemType, type.AccessPrefixInGeneratedFunction(), otherName, pooled,
                                   updateWhenAssigned: type.IsDataList());
            }
            else if (type.IsArray)
            {
                var elemType = type.GetElementType();
                SinkArrayUpdateFromWithFixedSize(sink, elemType, type.AccessPrefixInGeneratedFunction(), otherName,
                                                 pooled);
            }
            else if (type.IsDictionary())
            {
                Error($"Update from for dictionary ({type}) is not supported");
            }
            else
            {
                if (type != updateFromType)
                {
                    otherName = instanceCastedName;
                    sink.content($"var {instanceCastedName} = ({type.RealName(true)}){instanceName};");

                    var directUpdateSink = GenClassSink(type).Method(funcPrefix + UpdateFuncName, type, MethodType.Instance, typeof(void),
                                                                     $"{type.RealName(true)} {instanceName}{(pooled ? ", ObjectPool pool" : "")}");

                    directUpdateSink.content($"this.UpdateFrom(({updateFromType.RealName(true)})other{(pooled ? ", pool" : "")});");
                    directUpdateSink.classBuilder.inheritance($"I{(pooled ? "Pooled" : "")}UpdatableFrom<{type.RealName(true)}>");
                }
                if (type.IsControllable())
                {
                    GenClassSink(type)
                    .inheritance($"I{(pooled ? "Pooled" : "")}UpdatableFrom<{updateFromType.RealName(true)}>");
                }

                type.ProcessMembers(flag, true,
                                    memberInfo =>
                {
                    GenUpdateValueFromInstance(sink, memberInfo,
                                               memberInfo.valueTransformer($"{otherName}.{memberInfo.baseAccess}"), pooled);
                });
            }
        }
Esempio 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};");
            }
        }