C
C#3mo ago
zobweyt

Attributes confusion

hey! I'm having trouble choosing an approach when using attributes. I'm building a wrapper around System.Threading.RateLimiting. I have an attribute RateLimitAttribute which is responsible for the basic logic and creation of PartitionedRateLimiter. here’s the problem: I want to be able to create custom ignore policies (to have no limit in custom conditions) and pass them directly to the RateLimitAttribute, but I don’t know how to do this correctly and what approach to choose. initially I wanted to make a base class RateLimitPolicyAttribute for all policies and later use it like this:
[RateLimit]
[IgnoreOwner, IgnoreAdmins, IgnorePremiumUsers]
public static void Foo() => throw NotImplementedException();
[RateLimit]
[IgnoreOwner, IgnoreAdmins, IgnorePremiumUsers]
public static void Foo() => throw NotImplementedException();
but the policies here can exist without the main RateLimitAttribute also, I thought about passing the policies directly to the main attribute, but this approach is not possible because the values in attribute parameters must be constant, so I can't just pass a list of policies. additionally, it'll be a very long line in length if I have many policies how can I implement this most conveniently?
12 Replies
PixxelKick
PixxelKick3mo ago
Option 1: If these are user defined (not constants), then they have to pass in a list of Types most likely Option 2: If these are specific constants that you define and are an immutable list, I would just use a flagged Enum
zobweyt
zobweyt3mo ago
these are user defined (not constants) as for the list of types, how do you type them correctly? for example, just Type[] policies? but how do you get the needed method to execute without hard-coding its name in a string? I was trying to find something like "generic type" so I could use it like that: Type<BaseType>[] policies or should I just do it like that:
if (type is not BaseType baseType)
throw Exception();

baseType.MyMethod();
if (type is not BaseType baseType)
throw Exception();

baseType.MyMethod();
PixxelKick
PixxelKick3mo ago
You have to use reflection, it's why you'll notice many attributes take in Types as their params for basically this exact problem space
zobweyt
zobweyt3mo ago
thank you!! I'll look into it :)
canton7
canton73mo ago
Attributes can be generic these days. So you can do [RateLimit<SomeCustomPolicy>], with associated generic type constraints
zobweyt
zobweyt3mo ago
I thought about this too, but what if you need multiple policies? also, you won't be able to use the [RateLimit] without the generic type
canton7
canton73mo ago
Yeah, you can apply it multiple times, or have multiple versions which take different numbers of types, but it gets a bit messy You can have both [RateLimit] and [RateLimit<Foo>] easily though
zobweyt
zobweyt3mo ago
if I allow to use multiple [RateLimit] attributes, then there will be multiple PartitionedRateLimiter instances, so the logic might be duplicated however, maybe I still need to rework the core attribute logic to make this possible if there's no policy, then the rate limit should be applied to every request (which is the default policy) maybe I can do a DefaultPolicy and use it like that [RateLimit<DefaultPolicy>] well, it seems to be more customizable speaking globally, what would you prefer as a user of it? pass policies into one attribute as the argument, thereby making the string infinitely long and unreadable, or make several such attributes that accept the policy as a generic argument creating a long chain of attributes on several lines?
canton7
canton73mo ago
Personally I don't like using attributes for that sort of stuff, as it's awkward to customise them. If I need to instantiate my policy with a particular parameter, say, that gets awkward. Particularly if that parameter is only known at runtime
zobweyt
zobweyt3mo ago
also, all of these attributes will always be executed before processing the request until there is a negative result or all attributes check the conditions (this is because of the framework's nature for which I am trying to implement it). because of this, there may be conflicts: for example, I have this method:
[RateLimit<AdminPolicy>]
[RateLimit<DefaultPolicy>]
public static void Foo() => throw NotImplementedException();
[RateLimit<AdminPolicy>]
[RateLimit<DefaultPolicy>]
public static void Foo() => throw NotImplementedException();
although AdminPolicy skips all requests, the following attribute is always executed after it, which will be valid for all requests
canton7
canton73mo ago
I mean, everything you're saying here isn't set in stone. It's up to you to define how the attributes interact
zobweyt
zobweyt3mo ago
yeah, I'm of the same opinion, but the framework which I use decides the attributes interaction for me anyway, thank you so much for the suggestion! I'll try to implement something similar and compare it with other ideas :)
Want results from more Discord servers?
Add your server
More Posts
Setting Up a C# Backend with React Frontend and MySQL on VSCode - Need Guidance for .NET 8 CompatibiHey question guys lol, I am struggling so much right now. Here’s what I’m trying to do: I’m using VSMaui issues after changing namespaceyesterday I had the briliant idea of changing the name of my app because i made it open source and pRestSharp multipart request in from Unity fails with NRE after successfully sending requestWith this stack trace: ``` NullReferenceException: Object reference not set to an instance of an objWhen I set PublishAot to true, I get "Publish has encountered an error.When I set PublishAot to true, I get "Publish has encountered an error. We were unable to determine Blurring an Image in C#, working slowlySmall glitch but my algorithm for making this image blur is running super slow, going from the top oMy socket won't send data to 600 endpointsMy application sends a packet to 600 servers in order to gather data about active players and such. Help with Azure Cognitive Services?Currently I would like to add AI to my personal projects, I read about Azure cognitive services, I w✅ Need some help debugging EF Core db queryI am trying to get some information from the database. I am running this query: ```CS var ordersInLa✅ Seed cannot be added because of required property IDThe seed entity for entity type 'Series' cannot be added because no value was provided for the requiRazor Page Validation Error MessageFor "int" and "decimal" it gives a standard error message instead of my pre defined. "Is not valid f