diff --git a/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj b/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj
index 2c38452e..c7e656e8 100644
--- a/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj
+++ b/XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj
@@ -24,12 +24,12 @@
runtime; build; native; contentfiles; analyzers
-
-
+
+
-
+
all
runtime; build; native; contentfiles; analyzers
diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs
index 43162982..0216e8d5 100644
--- a/XmlSchemaClassGenerator.Tests/XmlTests.cs
+++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs
@@ -2578,5 +2578,91 @@ public void TestArrayItemAttribute()
var optionList = applicationType.GetProperty("OptionList");
Assert.Equal("Test_Generation_Namespace.T_OptionList", optionList.PropertyType.FullName);
}
+
+ [Fact]
+ public void CollectionSetterInAttributeGroupInterfaceIsPrivateIfCollectionSetterModeIsPrivate()
+ {
+ const string xsd = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ var generator = new Generator
+ {
+ NamespaceProvider = new NamespaceProvider
+ {
+ GenerateNamespace = key => "Test",
+ },
+ GenerateInterfaces = true,
+ CollectionSettersMode = CollectionSettersMode.Private
+ };
+ var contents = ConvertXml(nameof(CollectionSetterInAttributeGroupInterfaceIsPrivateIfCollectionSetterModeIsPrivate), xsd, generator).ToArray();
+ var assembly = Compiler.Compile(nameof(CollectionSetterInAttributeGroupInterfaceIsPrivateIfCollectionSetterModeIsPrivate), contents);
+
+ var interfaceProperty = assembly.GetType("Test.IAttrGroup")?.GetProperty("Attr");
+ var implementerProperty = assembly.GetType("Test.Element")?.GetProperty("Attr");
+ Assert.NotNull(interfaceProperty);
+ Assert.NotNull(implementerProperty);
+
+ var interfaceHasPublicSetter = interfaceProperty.GetSetMethod() != null;
+ var implementerHasPublicSetter = implementerProperty.GetSetMethod() != null;
+ Assert.False(interfaceHasPublicSetter);
+ Assert.False(implementerHasPublicSetter);
+ }
+
+ [Fact]
+ public void CollectionSetterInAttributeGroupInterfaceIsPublicIfCollectionSetterModeIsPublic()
+ {
+ const string xsd = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ var generator = new Generator
+ {
+ NamespaceProvider = new NamespaceProvider
+ {
+ GenerateNamespace = key => "Test",
+ },
+ GenerateInterfaces = true,
+ CollectionSettersMode = CollectionSettersMode.Public
+ };
+ var contents = ConvertXml(nameof(CollectionSetterInAttributeGroupInterfaceIsPublicIfCollectionSetterModeIsPublic), xsd, generator).ToArray();
+ var assembly = Compiler.Compile(nameof(CollectionSetterInAttributeGroupInterfaceIsPublicIfCollectionSetterModeIsPublic), contents);
+
+ var interfaceProperty = assembly.GetType("Test.IAttrGroup")?.GetProperty("Attr");
+ var implementerProperty = assembly.GetType("Test.Element")?.GetProperty("Attr");
+ Assert.NotNull(interfaceProperty);
+ Assert.NotNull(implementerProperty);
+
+ var interfaceHasPublicSetter = interfaceProperty.GetSetMethod() != null;
+ var implementerHasPublicSetter = implementerProperty.GetSetMethod() != null;
+ Assert.True(interfaceHasPublicSetter);
+ Assert.True(implementerHasPublicSetter);
+ }
}
}
diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs
index abae0b5b..3407c01b 100644
--- a/XmlSchemaClassGenerator/TypeModel.cs
+++ b/XmlSchemaClassGenerator/TypeModel.cs
@@ -756,6 +756,7 @@ private bool IsNullableValueType
private bool IsNullableReferenceType
{
+<<<<<<< HEAD
get
{
return DefaultValue == null
@@ -1126,6 +1127,386 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
typeDeclaration.Members.Add(specifiedProperty);
}
+=======
+ get
+ {
+ return DefaultValue == null
+ && IsNullable && (IsCollection || IsArray || IsList || PropertyType is ClassModel || PropertyType is SimpleModel model && !model.ValueType.IsValueType);
+ }
+ }
+
+ private bool IsNillableValueType
+ {
+ get
+ {
+ return IsNillable
+ && !(IsCollection || IsArray)
+ && ((PropertyType is EnumModel) || (PropertyType is SimpleModel model && model.ValueType.IsValueType));
+ }
+ }
+
+ private bool IsList
+ {
+ get
+ {
+ return Type.XmlSchemaType?.Datatype?.Variety == XmlSchemaDatatypeVariety.List;
+ }
+ }
+
+ private bool IsPrivateSetter
+ {
+ get
+ {
+ return Configuration.CollectionSettersMode == CollectionSettersMode.Private
+ && (IsCollection || IsArray || (IsList && IsAttribute));
+ }
+ }
+
+ private CodeTypeReference TypeReference
+ {
+ get
+ {
+ return PropertyType.GetReferenceFor(OwningType.Namespace,
+ collection: IsCollection || IsArray || (IsList && IsAttribute),
+ attribute: IsAttribute);
+ }
+ }
+
+ private void AddDocs(CodeTypeMember member)
+ {
+ var docs = new List(Documentation);
+
+ DocumentationModel.AddDescription(member.CustomAttributes, docs, Configuration);
+
+ if (PropertyType is SimpleModel simpleType)
+ {
+ docs.AddRange(simpleType.Documentation);
+ docs.AddRange(simpleType.Restrictions.Select(r => new DocumentationModel { Language = "en", Text = r.Description }));
+ member.CustomAttributes.AddRange(simpleType.GetRestrictionAttributes().ToArray());
+ }
+
+ member.Comments.AddRange(DocumentationModel.GetComments(docs, Configuration).ToArray());
+ }
+
+ private CodeAttributeDeclaration CreateDefaultValueAttribute(CodeTypeReference typeReference, CodeExpression defaultValueExpression)
+ {
+ var defaultValueAttribute = new CodeAttributeDeclaration(CodeUtilities.CreateTypeReference(typeof(DefaultValueAttribute), Configuration));
+ if (typeReference.BaseType == "System.Decimal")
+ {
+ defaultValueAttribute.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(typeof(decimal))));
+ defaultValueAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(DefaultValue)));
+ }
+ else
+ defaultValueAttribute.Arguments.Add(new CodeAttributeArgument(defaultValueExpression));
+
+ return defaultValueAttribute;
+ }
+
+ public void AddInterfaceMembersTo(CodeTypeDeclaration typeDeclaration)
+ {
+ CodeTypeMember member;
+
+ var propertyType = PropertyType;
+ var isNullableValueType = IsNullableValueType;
+ var isPrivateSetter = IsPrivateSetter;
+ var typeReference = TypeReference;
+
+ if (isNullableValueType && Configuration.GenerateNullables)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ typeReference = nullableType;
+ }
+
+ member = new CodeMemberProperty
+ {
+ Name = Name,
+ Type = typeReference,
+ HasGet = true,
+ HasSet = !isPrivateSetter
+ };
+
+ if (DefaultValue != null && IsNullable)
+ {
+ var defaultValueExpression = propertyType.GetDefaultValueFor(DefaultValue, IsAttribute);
+
+ if ((defaultValueExpression is CodePrimitiveExpression) || (defaultValueExpression is CodeFieldReferenceExpression)
+ && !CodeUtilities.IsXmlLangOrSpace(XmlSchemaName))
+ {
+ var defaultValueAttribute = CreateDefaultValueAttribute(typeReference, defaultValueExpression);
+ member.CustomAttributes.Add(defaultValueAttribute);
+ }
+ }
+
+ typeDeclaration.Members.Add(member);
+
+ AddDocs(member);
+ }
+
+ // ReSharper disable once FunctionComplexityOverflow
+ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBinding)
+ {
+ CodeTypeMember member;
+
+ var typeClassModel = TypeClassModel;
+ var isArray = IsArray;
+ var propertyType = PropertyType;
+ var isNullableValueType = IsNullableValueType;
+ var isNullableReferenceType = IsNullableReferenceType;
+ var isPrivateSetter = IsPrivateSetter;
+ var typeReference = TypeReference;
+
+ var requiresBackingField = withDataBinding || DefaultValue != null || IsCollection || isArray;
+ CodeMemberField backingField;
+
+ if (IsNillableValueType)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ backingField = new CodeMemberField(nullableType, OwningType.GetUniqueFieldName(this));
+ }
+ else
+ {
+ backingField = new CodeMemberField(typeReference, OwningType.GetUniqueFieldName(this))
+ {
+ Attributes = MemberAttributes.Private
+ };
+ }
+
+ var ignoreAttribute = new CodeAttributeDeclaration(CodeUtilities.CreateTypeReference(typeof(XmlIgnoreAttribute), Configuration));
+ var notMappedAttribute = new CodeAttributeDeclaration(CodeUtilities.CreateTypeReference("System.ComponentModel.DataAnnotations.Schema", "NotMappedAttribute", Configuration));
+ backingField.CustomAttributes.Add(ignoreAttribute);
+
+ if (requiresBackingField)
+ {
+ typeDeclaration.Members.Add(backingField);
+ }
+
+ if (DefaultValue == null || ((IsCollection || isArray || (IsList && IsAttribute)) && IsNullable))
+ {
+ var propertyName = Name;
+
+ if (isNullableValueType && Configuration.GenerateNullables && !(Configuration.UseShouldSerializePattern && !IsAttribute))
+ {
+ propertyName += "Value";
+ }
+
+ if (IsNillableValueType)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ member = new CodeMemberField(nullableType, propertyName);
+ }
+ else if (isNullableValueType && !IsAttribute && Configuration.UseShouldSerializePattern)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ member = new CodeMemberField(nullableType, propertyName);
+
+ typeDeclaration.Members.Add(new CodeMemberMethod
+ {
+ Attributes = MemberAttributes.Public,
+ Name = "ShouldSerialize" + propertyName,
+ ReturnType = new CodeTypeReference(typeof(bool)),
+ Statements =
+ {
+ new CodeSnippetExpression($"return {propertyName}.HasValue")
+ }
+ });
+ }
+ else
+ member = new CodeMemberField(typeReference, propertyName);
+
+ if (requiresBackingField)
+ {
+ member.Name += GetAccessors(member.Name, backingField.Name,
+ IsCollection || isArray ? PropertyValueTypeCode.Array : propertyType.GetPropertyValueTypeCode(),
+ isPrivateSetter, withDataBinding);
+ }
+ else
+ {
+ // hack to generate automatic property
+ member.Name += isPrivateSetter ? " { get; private set; }" : " { get; set; }";
+ }
+ }
+ else
+ {
+ var defaultValueExpression = propertyType.GetDefaultValueFor(DefaultValue, IsAttribute);
+ backingField.InitExpression = defaultValueExpression;
+
+ if (IsNillableValueType)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ member = new CodeMemberField(nullableType, Name);
+ }
+ else
+ member = new CodeMemberField(typeReference, Name);
+
+ member.Name += GetAccessors(member.Name, backingField.Name, propertyType.GetPropertyValueTypeCode(), false, withDataBinding);
+
+ if (IsNullable && ((defaultValueExpression is CodePrimitiveExpression) || (defaultValueExpression is CodeFieldReferenceExpression))
+ && !CodeUtilities.IsXmlLangOrSpace(XmlSchemaName))
+ {
+ var defaultValueAttribute = CreateDefaultValueAttribute(typeReference, defaultValueExpression);
+ member.CustomAttributes.Add(defaultValueAttribute);
+ }
+ }
+
+ member.Attributes = MemberAttributes.Public;
+ typeDeclaration.Members.Add(member);
+
+ AddDocs(member);
+
+ if (!IsNullable && Configuration.DataAnnotationMode != DataAnnotationMode.None)
+ {
+ var requiredAttribute = new CodeAttributeDeclaration(CodeUtilities.CreateTypeReference("System.ComponentModel.DataAnnotations", "RequiredAttribute", Configuration));
+ member.CustomAttributes.Add(requiredAttribute);
+ }
+
+ if (IsDeprecated)
+ {
+ // From .NET 3.5 XmlSerializer doesn't serialize objects with [Obsolete] >(
+ }
+
+ if (isNullableValueType)
+ {
+ bool generateNullablesProperty = Configuration.GenerateNullables;
+ bool generateSpecifiedProperty = true;
+
+ if (generateNullablesProperty && Configuration.UseShouldSerializePattern && !IsAttribute)
+ {
+ generateNullablesProperty = false;
+ generateSpecifiedProperty = false;
+ }
+
+ var specifiedName = generateNullablesProperty ? Name + "Value" : Name;
+ CodeMemberField specifiedMember = null;
+ if (generateSpecifiedProperty)
+ {
+ specifiedMember = new CodeMemberField(typeof(bool), specifiedName + "Specified { get; set; }");
+ specifiedMember.CustomAttributes.Add(ignoreAttribute);
+ if (Configuration.EntityFramework && generateNullablesProperty) { specifiedMember.CustomAttributes.Add(notMappedAttribute); }
+ specifiedMember.Attributes = MemberAttributes.Public;
+ var specifiedDocs = new[] { new DocumentationModel { Language = "en", Text = string.Format("Gets or sets a value indicating whether the {0} property is specified.", Name) },
+ new DocumentationModel { Language = "de", Text = string.Format("Ruft einen Wert ab, der angibt, ob die {0}-Eigenschaft spezifiziert ist, oder legt diesen fest.", Name) } };
+ specifiedMember.Comments.AddRange(DocumentationModel.GetComments(specifiedDocs, Configuration).ToArray());
+ typeDeclaration.Members.Add(specifiedMember);
+
+ var specifiedMemberPropertyModel = new PropertyModel(Configuration)
+ {
+ Name = specifiedName + "Specified"
+ };
+
+ Configuration.MemberVisitor(specifiedMember, specifiedMemberPropertyModel);
+ }
+
+ if (generateNullablesProperty)
+ {
+ var nullableType = CodeUtilities.CreateTypeReference(typeof(Nullable<>), Configuration);
+ nullableType.TypeArguments.Add(typeReference);
+ var nullableMember = new CodeMemberProperty
+ {
+ Type = nullableType,
+ Name = Name,
+ HasSet = true,
+ HasGet = true,
+ Attributes = MemberAttributes.Public | MemberAttributes.Final,
+ };
+ nullableMember.CustomAttributes.Add(ignoreAttribute);
+ nullableMember.Comments.AddRange(member.Comments);
+
+ var specifiedExpression = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), specifiedName + "Specified");
+ var valueExpression = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name + "Value");
+ var conditionStatement = new CodeConditionStatement(specifiedExpression,
+ new CodeStatement[] { new CodeMethodReturnStatement(valueExpression) },
+ new CodeStatement[] { new CodeMethodReturnStatement(new CodePrimitiveExpression(null)) });
+ nullableMember.GetStatements.Add(conditionStatement);
+
+ var getValueOrDefaultExpression = new CodeMethodInvokeExpression(new CodePropertySetValueReferenceExpression(), "GetValueOrDefault");
+ var setValueStatement = new CodeAssignStatement(valueExpression, getValueOrDefaultExpression);
+ var hasValueExpression = new CodePropertyReferenceExpression(new CodePropertySetValueReferenceExpression(), "HasValue");
+ var setSpecifiedStatement = new CodeAssignStatement(specifiedExpression, hasValueExpression);
+
+ var statements = new List();
+ if (withDataBinding)
+ {
+ var ifNotEquals = new CodeConditionStatement(
+ new CodeBinaryOperatorExpression(
+ new CodeBinaryOperatorExpression(
+ new CodeMethodInvokeExpression(valueExpression, "Equals", getValueOrDefaultExpression),
+ CodeBinaryOperatorType.ValueEquality,
+ new CodePrimitiveExpression(false)
+ ),
+ CodeBinaryOperatorType.BooleanOr,
+ new CodeBinaryOperatorExpression(
+ new CodeMethodInvokeExpression(specifiedExpression, "Equals", hasValueExpression),
+ CodeBinaryOperatorType.ValueEquality,
+ new CodePrimitiveExpression(false)
+ )
+ ),
+ setValueStatement,
+ setSpecifiedStatement,
+ new CodeExpressionStatement(new CodeMethodInvokeExpression(null, "OnPropertyChanged",
+ new CodePrimitiveExpression(Name)))
+ );
+ statements.Add(ifNotEquals);
+ }
+ else
+ {
+ statements.Add(setValueStatement);
+ statements.Add(setSpecifiedStatement);
+ }
+
+ nullableMember.SetStatements.AddRange(statements.ToArray());
+
+ typeDeclaration.Members.Add(nullableMember);
+
+ var editorBrowsableAttribute = new CodeAttributeDeclaration(CodeUtilities.CreateTypeReference(typeof(EditorBrowsableAttribute), Configuration));
+ editorBrowsableAttribute.Arguments.Add(new CodeAttributeArgument(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(CodeUtilities.CreateTypeReference(typeof(EditorBrowsableState), Configuration)), "Never")));
+ specifiedMember?.CustomAttributes.Add(editorBrowsableAttribute);
+ member.CustomAttributes.Add(editorBrowsableAttribute);
+ if (Configuration.EntityFramework) { member.CustomAttributes.Add(notMappedAttribute); }
+
+ Configuration.MemberVisitor(nullableMember, this);
+ }
+ }
+ else if ((IsCollection || isArray || (IsList && IsAttribute)) && IsNullable)
+ {
+ var specifiedProperty = new CodeMemberProperty
+ {
+ Type = CodeUtilities.CreateTypeReference(typeof(bool), Configuration),
+ Name = Name + "Specified",
+ HasSet = false,
+ HasGet = true,
+ };
+ specifiedProperty.CustomAttributes.Add(ignoreAttribute);
+ if (Configuration.EntityFramework) { specifiedProperty.CustomAttributes.Add(notMappedAttribute); }
+ specifiedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
+
+ var listReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name);
+ var collectionType = Configuration.CollectionImplementationType ?? Configuration.CollectionType;
+ var countProperty = collectionType == typeof(System.Array) ? "Length" : "Count";
+ var countReference = new CodePropertyReferenceExpression(listReference, countProperty);
+ var notZeroExpression = new CodeBinaryOperatorExpression(countReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(0));
+ if (Configuration.CollectionSettersMode is CollectionSettersMode.PublicWithoutConstructorInitialization or CollectionSettersMode.Public)
+ {
+ var notNullExpression = new CodeBinaryOperatorExpression(listReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
+ notZeroExpression = new CodeBinaryOperatorExpression(notNullExpression, CodeBinaryOperatorType.BooleanAnd, notZeroExpression);
+ }
+ var returnStatement = new CodeMethodReturnStatement(notZeroExpression);
+ specifiedProperty.GetStatements.Add(returnStatement);
+
+ var specifiedDocs = new[] { new DocumentationModel { Language = "en", Text = string.Format("Gets a value indicating whether the {0} collection is empty.", Name) },
+ new DocumentationModel { Language = "de", Text = string.Format("Ruft einen Wert ab, der angibt, ob die {0}-Collection leer ist.", Name) } };
+ specifiedProperty.Comments.AddRange(DocumentationModel.GetComments(specifiedDocs, Configuration).ToArray());
+
+ Configuration.MemberVisitor(specifiedProperty, this);
+
+ typeDeclaration.Members.Add(specifiedProperty);
+ }
+
+>>>>>>> f18798bfb37ce1d25d78564badae1d6b405d4136
if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
{
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.AllowNullAttribute"));