Skip to content

Commit

Permalink
Support nullable Enum properties, fixes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-jitbit committed May 5, 2023
1 parent 24973c7 commit ab0378c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
7 changes: 7 additions & 0 deletions MapDataReader.Tests/TestActualCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class MyObject


public MyEnum Dude { get; set; }
public MyEnum? NullableDude { get; set; }
public string Name { get; set; }

public int GetOnly { get; } = 123; //property without public setter!
Expand Down Expand Up @@ -123,6 +124,12 @@ public void TestEnumAssign()

o.SetPropertyByName("Dude", (byte)2); //let's shove a BYTE in there!
Assert.IsTrue(o.Dude == MyEnum.Third); //eat this, boxing!!

o.SetPropertyByName("NullableDude", 1);
Assert.IsTrue(o.NullableDude == MyEnum.SecondDude);

o.SetPropertyByName("NullableDude", MyEnum.FirstDude);
Assert.IsTrue(o.NullableDude == MyEnum.FirstDude);
}

[TestMethod]
Expand Down
21 changes: 19 additions & 2 deletions MapDataReader/MapperGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ private static void SetPropertyByUpperName(this {typeNodeSymbol.FullName()} targ
{"\r\n" + allProperties.Select(p =>
{
var pTypeName = p.Type.FullName();
if (p.Type.IsReferenceType || pTypeName.EndsWith("?")) //ref types and nullable type - just cast to property type
if (p.Type.IsReferenceType || (pTypeName.EndsWith("?") && !p.Type.IsNullableEnum())) //ref types and nullable type - just cast to property type (unless nullable Enum)
{
return $@" if (name == ""{p.Name.ToUpperInvariant()}"") {{ target.{p.Name} = value as {pTypeName}; return; }}";
}
else if (p.Type.TypeKind == TypeKind.Enum) //enum? pre-convert to underlying type then to int, you can't cast a boxed int to enum directly. Also to support assigning "smallint" database col to int32 (for example), which does not work at first (you can't cast a boxed "byte" to "int")
else if (p.Type.TypeKind == TypeKind.Enum || p.Type.IsNullableEnum()) //enum? pre-convert to underlying type then to int, you can't cast a boxed int to enum directly. Also to support assigning "smallint" database col to int32 (for example), which does not work at first (you can't cast a boxed "byte" to "int")
{
return $@" if (value != null && name == ""{p.Name.ToUpperInvariant()}"") {{ target.{p.Name} = ({pTypeName})(value.GetType() == typeof(int) ? (int)value : (int)Convert.ChangeType(value, typeof(int))); return; }}"; //pre-convert enums to int first (after unboxing, see below)
}
Expand Down Expand Up @@ -149,5 +150,21 @@ internal static IEnumerable<IPropertySymbol> GetAllSettableProperties(this IType

return result;
}

//checks if type is a nullable num
internal static bool IsNullableEnum(this ITypeSymbol symbol)
{
//tries to get underlying non-nullable type from nullable type
//and then check if it's Enum
if (symbol.NullableAnnotation == NullableAnnotation.Annotated
&& symbol is INamedTypeSymbol namedType
&& namedType.IsValueType
&& namedType.IsGenericType
&& namedType.ConstructedFrom?.ToDisplayString() == "System.Nullable<T>"
)
return namedType.TypeArguments[0].TypeKind == TypeKind.Enum;

return false;
}
}
}

0 comments on commit ab0378c

Please sign in to comment.