Unable to check for existence of unbound generic typed attribute on type

I'm looking to build out the behavior of a Blazor component based on the attributes applied to the type:
public abstract record EditStartAction();

public sealed class CanEdit<TEditAction> : Attribute
where TEditAction : EditStartAction, new()
{
}

public record MyCreateStartAction : CreateStartAction
{
}

[GenerateBehavior]
[CanEdit<MyCreateStartAction>]
public partial class TestTable : FluxorComponent
{
}

public sealed class GenerateBehavior : TypeAspect
{
public override void BuildAspect(IAspectBuilder<INamedType> builder)
{
var supportsEditing = builder.Target.Attributes.OfAttributeType(typeof(CanEditAttribute<>)).Any();

if (supportsEditing)
{
//Introduce a method
}
}
}
public abstract record EditStartAction();

public sealed class CanEdit<TEditAction> : Attribute
where TEditAction : EditStartAction, new()
{
}

public record MyCreateStartAction : CreateStartAction
{
}

[GenerateBehavior]
[CanEdit<MyCreateStartAction>]
public partial class TestTable : FluxorComponent
{
}

public sealed class GenerateBehavior : TypeAspect
{
public override void BuildAspect(IAspectBuilder<INamedType> builder)
{
var supportsEditing = builder.Target.Attributes.OfAttributeType(typeof(CanEditAttribute<>)).Any();

if (supportsEditing)
{
//Introduce a method
}
}
}
In one of the logging examples, we do something similar with:
private static bool IsSensitive(IParameter parameter) => parameter.Attributes.OfAttributeType(typof(SensitiveDataAttribute)).Any();
private static bool IsSensitive(IParameter parameter) => parameter.Attributes.OfAttributeType(typof(SensitiveDataAttribute)).Any();
This works fine, but in my larger example above, it never shows the introduced method even though it appears to be the same thing. Am I doing something wrong or does the OfAttributeType method not handle unbound generic types in a typeof well unlike non-generic attributes? Thanks!
5 Replies
Xaniff
Xaniff13mo ago
Testing further, if I add an attribute without a generic type:
[AttributeUsage(AttributeTargets.Class)]
public class CanDoThingsAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class CanDoThingsAttribute : Attribute
{
}
and decorate my target class accordingly:
[GenerateBehavior]
[CanEdit<MyCreateStartAction>]
[CanDoThings]
public partial class TestTable : FluxorComponent
{
}
[GenerateBehavior]
[CanEdit<MyCreateStartAction>]
[CanDoThings]
public partial class TestTable : FluxorComponent
{
}
And then update the aspect to include a check for this attrbute:
var supportsSomething = builder.Target.Attributes.Any(typeof(CanDoThingsAttribute));`
var supportsSomething = builder.Target.Attributes.Any(typeof(CanDoThingsAttribute));`
And then finally update the logic to add the method or not:
if (supportsCreating || supportsSomething)
{
}
if (supportsCreating || supportsSomething)
{
}
Then it works, indicating that it's an identification issue with the unbound generically typed attribute as if there's no generic type involved, it works as expected.
Gael Fraiteur
Gael Fraiteur13mo ago
I have filed an enhancement request. In the meantime, you should use something like this:
parameter.Attributes.Any( a => a.Type is INamedType namedType && namedType.Is( typeof(Foo<>) ) )
parameter.Attributes.Any( a => a.Type is INamedType namedType && namedType.Is( typeof(Foo<>) ) )
Xaniff
Xaniff13mo ago
That doesn't seem to be working either - when using:
var supportsCreating = builder.Target.Attributes.Any(a => a.Type is { } namedType && namedType.Is(typeof(CanCreateAttribute<>)));
var supportsCreating = builder.Target.Attributes.Any(a => a.Type is { } namedType && namedType.Is(typeof(CanCreateAttribute<>)));
if (supportsCreating)
{
//Introduce method
}
if (supportsCreating)
{
//Introduce method
}
The method is never introduced in the preview even though the attribute is attached:
[GenerateBehavior]
[CanCreate<MyCreateStartAction>]
public partial class TestTable : FluxorComponent
{
}
[GenerateBehavior]
[CanCreate<MyCreateStartAction>]
public partial class TestTable : FluxorComponent
{
}
Gael Fraiteur
Gael Fraiteur13mo ago
Sorry, I forgot the TypeDefinition part:
parameter.Attributes.Any( a => a.Type is INamedType namedType && namedType.TypeDefinition.Is( typeof(Foo<>) ) )
parameter.Attributes.Any( a => a.Type is INamedType namedType && namedType.TypeDefinition.Is( typeof(Foo<>) ) )
Xaniff
Xaniff13mo ago
That did the trick. Thank you!