Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use attributes reserved for compiler in CodeGen #472

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 7 additions & 17 deletions src/OpenRiaServices.Tools/Framework/DataContractProxyGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ internal abstract class DataContractProxyGenerator : ProxyGenerator
{
private readonly bool _isRoundtripType;
private readonly IDictionary<Type, CodeTypeDeclaration> _typeMapping;
private readonly List<Type> _attributeTypesToFilter;

/// <summary>
/// Initializes a new instance of the <see cref="DataContractProxyGenerator"/> class.
Expand All @@ -37,19 +36,6 @@ protected DataContractProxyGenerator(CodeDomClientCodeGenerator proxyGenerator,
_typeMapping = typeMapping;
NotificationMethodGen = new NotificationMethodGenerator(proxyGenerator);
_isRoundtripType = type.Attributes()[typeof(RoundtripOriginalAttribute)] != null;

// Add attributes which should be used to filter the attributes on type to be generated
_attributeTypesToFilter = new()
{
// DataContractAttribute and KnownTypeAttribute are handled seperatly
typeof(DataContractAttribute),
typeof(KnownTypeAttribute),
#if NET
// Filter out NullableAttribute and NullableContextAttribute, should only be used by compiler
Type.GetType("System.Runtime.CompilerServices.NullableAttribute"),
Type.GetType("System.Runtime.CompilerServices.NullableContextAttribute"),
#endif
};
}

/// <summary>
Expand Down Expand Up @@ -399,7 +385,8 @@ protected virtual void GenerateProperty(PropertyDescriptor propertyDescriptor)
property.Name = propertyName;
property.Type = propTypeReference;
property.Attributes = MemberAttributes.Public | MemberAttributes.Final; // final needed, else becomes virtual
List<Attribute> propertyAttributes = propertyDescriptor.ExplicitAttributes().Cast<Attribute>().ToList();
var propertyAttributes = propertyDescriptor.ExplicitAttributes().Cast<Attribute>()
.Where(a => a.GetType().Namespace != "System.Runtime.CompilerServices").ToList(); //Do not use attributes only used by the compiler
SandstromErik marked this conversation as resolved.
Show resolved Hide resolved

// Generate <summary> for property
string comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_Property_Summary_Comment, propertyName);
Expand Down Expand Up @@ -549,8 +536,11 @@ private IEnumerable<Attribute> FilterTypeAttributes(AttributeCollection typeAttr
}
}

// Filter out attributes in filteredAttributes and attributeTypesToFilter
return typeAttributes.Cast<Attribute>().Where(a => !_attributeTypesToFilter.Contains(a.GetType()) && !filteredAttributes.Contains(a));
// Filter out attributes in filteredAttributes, attributes which should only be used by the compiler,
// DataContractAttribute and KnownTypeAttribute since they are handled seperatly
return typeAttributes.Cast<Attribute>().Where(a => a.GetType().Namespace != "System.Runtime.CompilerServices"
&& a.GetType() != typeof(DataContractAttribute) && a.GetType() != typeof(KnownTypeAttribute)
&& !filteredAttributes.Contains(a));
}

/// <summary>
Expand Down
31 changes: 31 additions & 0 deletions src/OpenRiaServices.Tools/Test/CodeGenRequiredModifierTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if NET7_0_OR_GREATER //required modifier does not work before net7
using System.ComponentModel.DataAnnotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace OpenRiaServices.Tools.Test;

/// <summary>
/// CodeGen tests for the required modifier
/// </summary>
[TestClass]
public class CodeGenRequiredModifierTests
{
[TestMethod]
[Description("CodeGen does not apply compiler exclusive attribute for required")]
public void CodeGen_Required_Modifier_Dont_Use_Compiler_Attributes()
SandstromErik marked this conversation as resolved.
Show resolved Hide resolved
{
MockSharedCodeService sts = TestHelper.CreateCommonMockSharedCodeService();
string generatedCode = TestHelper.GenerateCodeAssertSuccess("C#", new Type[] {typeof(Mock_CG_Required_Entity_DomainService) }, null, sts);
TestHelper.AssertGeneratedCodeDoesNotContain(generatedCode, "RequiredMember");
}
}

public class Mock_CG_Required_Entity_DomainService : GenericDomainService<Mock_CG_Required_Entity> { }

public class Mock_CG_Required_Entity
{
[Key]
public required string RequiredProperty { get; set; }
}
#endif
Loading