{"record":{"id":"db59a882c5395486","repo":"egametang/ET","slug":"runtimetype-fullname","errorCode":null,"errorMessage":"{runtimeType.FullName} 缺少可用于导出的公共构造函数。必须通过构造函数提供的成员: {names}。请补充例如 [BsonConstructor] public {runtimeType.Name}({parameters})","messagePattern":"(.+?) 缺少可用于导出的公共构造函数。必须通过构造函数提供的成员: (.+?)。请补充例如 \\[BsonConstructor\\] public (.+?)\\((.+?)\\)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.config/Scripts/Model/Share/CSharpObjectCodeEmitter.cs","lineNumber":414,"sourceCode":"                {\n                    continue;\n                }\n\n                matches.Add(match);\n            }\n\n            ConstructorMatch attributeMatch = matches.SingleOrDefault(match => match.Constructor.GetCustomAttribute<BsonConstructorAttribute>() != null);\n            if (attributeMatch != null)\n            {\n                return attributeMatch;\n            }\n\n            if (matches.Count == 1)\n            {\n                return matches[0];\n            }\n\n            throw new NotSupportedException(this.BuildMissingConstructorMessage(runtimeType, ctorMembers));\n        }\n\n        private bool TryMatchConstructor(ConstructorInfo constructor, List<SerializableMember> ctorMembers, out ConstructorMatch match)\n        {\n            match = null;\n\n            ParameterInfo[] parameters = constructor.GetParameters();\n            Dictionary<string, SerializableMember> membersByKey = this.BuildConstructorMemberLookup(ctorMembers);\n            List<ConstructorArgument> arguments = new();\n            HashSet<SerializableMember> boundMembers = new();\n\n            foreach (ParameterInfo parameter in parameters)\n            {\n                if (!membersByKey.TryGetValue(parameter.Name ?? string.Empty, out SerializableMember member))\n                {\n                    if (parameter.IsOptional)\n                    {\n                        continue;","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.config/Scripts/Model/Share/CSharpObjectCodeEmitter.cs#L396-L432","documentation":"Thrown by ResolveConstructor when emitting a complex object: the emitter needs a public constructor whose parameters (by name, case-insensitively, and by exact type) bind ALL serializable constructor-members, and either no constructor matched, or more than one matched without a [BsonConstructor] tiebreaker. The message lists the required member names and a suggested signature to copy.","triggerScenarios":"A serialized class has only a parameterless constructor but requires member-initialized reconstruction; the constructor parameter names do not match the member/serialization names; parameter types differ (e.g. member is long, ctor takes int); multiple candidate constructors exist and none is annotated with [BsonConstructor].","commonSituations":"Adding required (non-default) fields to a record-like config class without updating the constructor; renaming a member but not the matching ctor parameter; using init-only properties the emitter cannot supply via the ctor.","solutions":["Add a public constructor whose parameters match the reported members by name (case-insensitive) and exact type, as suggested in the message.","If multiple constructors qualify, annotate the canonical one with [BsonConstructor] so it is chosen unambiguously.","Ensure parameter names align with member names or [BsonElement]/serialization names the emitter looks up.","Remove or mark non-essential members [non-serialized] so the required member set shrinks to a ctor you already have."],"exampleFix":"// before\npublic class Reward\n{\n    public int Id { get; set; }\n    public int Count { get; set; }\n    public Reward() { } // no matching ctor for {Id, Count}\n}\n// after\npublic class Reward\n{\n    public int Id { get; set; }\n    public int Count { get; set; }\n    [BsonConstructor]\n    public Reward(int id, int count) { Id = id; Count = count; }\n}","handlingStrategy":"type-guard","validationCode":"// in a test, attempt emission of a sample instance to surface ctor issues early\nvar emitter = new CSharpObjectCodeEmitter();\ntry { emitter.Emit(sampleInstance); }\ncatch (NotSupportedException ex) { Assert.Fail(ex.Message); }","typeGuard":"static bool HasReconstructableCtor(Type t)\n{\n    // a public ctor exists whose parameter names/types cover all public settable members\n    var memberNames = t.GetFields().Select(f => f.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);\n    return t.GetConstructors().Any(c =>\n        c.GetParameters().All(p => p.IsOptional || memberNames.Contains(p.Name)));\n}","tryCatchPattern":null,"preventionTips":["Keep one canonical reconstructing constructor per exported class and annotate it [BsonConstructor].","Match constructor parameter names to member names (case-insensitive) and exact types.","Add a test that emits a sample of every exported type."],"tags":["csharp","unity","config","serialization","code-emitter","reflection"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}