Skip to content

Commit

Permalink
Add CollectionSettersMode.InitWithoutConstructorInitialization
Browse files Browse the repository at this point in the history
  • Loading branch information
mganss committed Dec 14, 2023
1 parent e96828d commit d400ed3
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
2 changes: 2 additions & 0 deletions XmlSchemaClassGenerator.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
"puwci" or "PublicWithoutConstructorInitialization" =>
CollectionSettersMode.PublicWithoutConstructorInitialization,
"in" or "Init" => CollectionSettersMode.Init,
"inwci" or "InitWithoutConstructorInitialization" =>
CollectionSettersMode.InitWithoutConstructorInitialization,
_ => CollectionSettersMode.Private
};
}},
Expand Down
38 changes: 37 additions & 1 deletion XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,42 @@ public void TestListWithPublicPropertySettersWithoutConstructors()
}
}

[Fact]
public void TestListWithInitPropertySetters()
{
var assembly = Compiler.Generate("ListPublic", ListPattern, new Generator
{
GenerateNullables = true,
IntegerDataType = typeof(int),
DataAnnotationMode = DataAnnotationMode.All,
GenerateDesignerCategoryAttribute = false,
GenerateComplexTypesForCollections = true,
EntityFramework = false,
GenerateInterfaces = true,
NamespacePrefix = "List",
GenerateDescriptionAttribute = true,
TextValuePropertyName = "Value",
CollectionSettersMode = CollectionSettersMode.Init
});
Assert.NotNull(assembly);
var myClassType = assembly.GetType("List.MyClass");
Assert.NotNull(myClassType);
var iListType = typeof(Collection<>);
var collectionPropertyInfos = myClassType.GetProperties().Where(p => p.PropertyType.IsGenericType && iListType.IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition())).OrderBy(p => p.Name).ToList();
var publicCollectionPropertyInfos = collectionPropertyInfos.Where(p => p.SetMethod.IsPublic).OrderBy(p => p.Name).ToList();
Assert.NotEmpty(collectionPropertyInfos);
Assert.Equal(collectionPropertyInfos, publicCollectionPropertyInfos);
var requiredCustomModifiers = collectionPropertyInfos.Select(p => p.SetMethod.ReturnParameter.GetRequiredCustomModifiers()).ToList();
Assert.Equal(collectionPropertyInfos.Count, requiredCustomModifiers.Count);
Assert.All(requiredCustomModifiers, m => Assert.Contains(typeof(System.Runtime.CompilerServices.IsExternalInit), m));

var myClassInstance = Activator.CreateInstance(myClassType);
foreach (var collectionPropertyInfo in publicCollectionPropertyInfos)
{
Assert.NotNull(collectionPropertyInfo.GetValue(myClassInstance));
}
}

[Fact]
public void TestListWithInitPropertySettersWithoutConstructors()
{
Expand All @@ -339,7 +375,7 @@ public void TestListWithInitPropertySettersWithoutConstructors()
NamespacePrefix = "List",
GenerateDescriptionAttribute = true,
TextValuePropertyName = "Value",
CollectionSettersMode = CollectionSettersMode.Init
CollectionSettersMode = CollectionSettersMode.InitWithoutConstructorInitialization
});
Assert.NotNull(assembly);
var myClassType = assembly.GetType("List.MyClass");
Expand Down
6 changes: 5 additions & 1 deletion XmlSchemaClassGenerator/CollectionSettersMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public enum CollectionSettersMode
/// <summary>
/// All collections setters are init-only
/// </summary>
Init
Init,
/// <summary>
/// All collections setters are init-only and backing collections fields are not initialized in constructors
/// </summary>
InitWithoutConstructorInitialization
}
}
6 changes: 3 additions & 3 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
var setter = Configuration.CollectionSettersMode switch
{
CollectionSettersMode.Private when IsEnumerable => "private set",
CollectionSettersMode.Init when IsEnumerable => "init",
CollectionSettersMode.Init or CollectionSettersMode.InitWithoutConstructorInitialization when IsEnumerable => "init",
_ => "set"
};
member.Name += GetAccessors(backingField, withDataBinding, propertyValueTypeCode, setter);
Expand Down Expand Up @@ -874,7 +874,7 @@ [new CodeMethodReturnStatement(valueExpression)],
var countProperty = collectionType == typeof(Array) ? nameof(Array.Length) : nameof(List<int>.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 or CollectionSettersMode.Init)
if (Configuration.CollectionSettersMode is CollectionSettersMode.PublicWithoutConstructorInitialization or CollectionSettersMode.Public or CollectionSettersMode.Init or CollectionSettersMode.InitWithoutConstructorInitialization)
{
var notNullExpression = new CodeBinaryOperatorExpression(listReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
notZeroExpression = new CodeBinaryOperatorExpression(notNullExpression, CodeBinaryOperatorType.BooleanAnd, notZeroExpression);
Expand Down Expand Up @@ -933,7 +933,7 @@ [new CodeMethodReturnStatement(valueExpression)],

// initialize List<>
if (isEnumerable && (Configuration.CollectionSettersMode != CollectionSettersMode.PublicWithoutConstructorInitialization)
&& (Configuration.CollectionSettersMode != CollectionSettersMode.Init))
&& (Configuration.CollectionSettersMode != CollectionSettersMode.InitWithoutConstructorInitialization))
{
var constructor = typeDeclaration.Members.OfType<CodeConstructor>().FirstOrDefault();

Expand Down

0 comments on commit d400ed3

Please sign in to comment.