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};"); }
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};"); } }