@@ -98,16 +98,97 @@ public override CodeTypeDeclaration Generate()
9898 classDeclaration . BaseTypes . Add ( BaseClass . GetReferenceFor ( Namespace ) ) ;
9999
100100 // When a derived class has a simpleContent restriction with enum facets (TextValueType != null),
101- // we generate the enum type but do NOT add a new Value property in the derived class.
102- // This is because the C# XmlSerializer has limitations when dealing with simpleContent
103- // restrictions in inheritance hierarchies - it cannot handle a derived class that adds
104- // a new XmlText property when the base class already has one.
105- //
106- // The enum type is still generated (in ModelBuilder) and can be used for validation/conversion manually:
107- // e.g., var enumValue = (MyEnum)Enum.Parse(typeof(MyEnum), instance.Value);
108- //
109- // This is a compromise to work within XmlSerializer's constraints while still providing
110- // the enum type that users requested in issue #561.
101+ // we generate an adapter property that allows strongly-typed access to the enum values.
102+ // We cannot add a new XmlText property because the XmlSerializer doesn't allow it when
103+ // the base class already has one. Instead, we use an [XmlIgnore] adapter property.
104+ if ( TextValueType != null && ! string . IsNullOrEmpty ( Configuration . TextValuePropertyName ) )
105+ {
106+ var textName = Configuration . TextValuePropertyName ;
107+ var enumTypeReference = TextValueType . GetReferenceFor ( Namespace ) ;
108+ var nullableEnumTypeReference = new CodeTypeReference ( typeof ( Nullable < > ) ) ;
109+ nullableEnumTypeReference . TypeArguments . Add ( enumTypeReference ) ;
110+
111+ // Create the EnumValue adapter property
112+ var enumValueProperty = new CodeMemberProperty
113+ {
114+ Name = "EnumValue" ,
115+ Type = nullableEnumTypeReference ,
116+ Attributes = MemberAttributes . Public ,
117+ HasGet = true ,
118+ HasSet = true
119+ } ;
120+
121+ // Add [XmlIgnore] attribute
122+ var ignoreAttribute = AttributeDecl < XmlIgnoreAttribute > ( ) ;
123+ enumValueProperty . CustomAttributes . Add ( ignoreAttribute ) ;
124+
125+ // Getter: Try to parse the Value property to enum
126+ // if (Enum.TryParse(typeof(EnumType), Value, true, out var result))
127+ // return (EnumType)result;
128+ // return null;
129+ var resultVariable = new CodeVariableDeclarationStatement ( typeof ( object ) , "result" ) ;
130+ var tryParseCondition = new CodeMethodInvokeExpression (
131+ new CodeTypeReferenceExpression ( typeof ( Enum ) ) ,
132+ "TryParse" ,
133+ new CodeTypeOfExpression ( enumTypeReference ) ,
134+ new CodePropertyReferenceExpression (
135+ new CodeThisReferenceExpression ( ) ,
136+ textName ) ,
137+ new CodePrimitiveExpression ( true ) ,
138+ new CodeDirectionExpression ( FieldDirection . Out , new CodeVariableReferenceExpression ( "result" ) ) ) ;
139+
140+ var returnCastResult = new CodeMethodReturnStatement (
141+ new CodeCastExpression (
142+ nullableEnumTypeReference ,
143+ new CodeVariableReferenceExpression ( "result" ) ) ) ;
144+
145+ var ifTryParse = new CodeConditionStatement (
146+ tryParseCondition ,
147+ returnCastResult ) ;
148+
149+ enumValueProperty . GetStatements . Add ( resultVariable ) ;
150+ enumValueProperty . GetStatements . Add ( ifTryParse ) ;
151+ enumValueProperty . GetStatements . Add ( new CodeMethodReturnStatement ( new CodePrimitiveExpression ( null ) ) ) ;
152+
153+ // Setter: Value = value?.ToString();
154+ // Since CodeDOM doesn't support null-conditional operator, we need to check and set
155+ var valueNotNull = new CodeBinaryOperatorExpression (
156+ new CodePropertySetValueReferenceExpression ( ) ,
157+ CodeBinaryOperatorType . IdentityInequality ,
158+ new CodePrimitiveExpression ( null ) ) ;
159+
160+ var setToString = new CodeAssignStatement (
161+ new CodePropertyReferenceExpression (
162+ new CodeThisReferenceExpression ( ) ,
163+ textName ) ,
164+ new CodeMethodInvokeExpression (
165+ new CodePropertySetValueReferenceExpression ( ) ,
166+ "ToString" ) ) ;
167+
168+ var setToNull = new CodeAssignStatement (
169+ new CodePropertyReferenceExpression (
170+ new CodeThisReferenceExpression ( ) ,
171+ textName ) ,
172+ new CodePrimitiveExpression ( null ) ) ;
173+
174+ enumValueProperty . SetStatements . Add (
175+ new CodeConditionStatement (
176+ valueNotNull ,
177+ new CodeStatement [ ] { setToString } ,
178+ new CodeStatement [ ] { setToNull } ) ) ;
179+
180+ var docs = new List < DocumentationModel > {
181+ new ( ) { Language = English , Text = "Gets or sets the typed value of the text content." } ,
182+ new ( ) { Language = German , Text = "Ruft den typisierten Wert des Textinhalts ab oder legt diesen fest." }
183+ } ;
184+
185+ enumValueProperty . Comments . AddRange ( GetComments ( docs ) . ToArray ( ) ) ;
186+
187+ classDeclaration . Members . Add ( enumValueProperty ) ;
188+
189+ var enumValuePropertyModel = new PropertyModel ( Configuration , "EnumValue" , TextValueType , this ) ;
190+ Configuration . MemberVisitor ( enumValueProperty , enumValuePropertyModel ) ;
191+ }
111192 }
112193 else if ( ! string . IsNullOrEmpty ( Configuration . TextValuePropertyName ) )
113194 {
0 commit comments