dreadfullydistinct
LoggerMessage organisation
Looking for some insight in how people using SG logging organise their methods.
Do you have them inside the class?
disadvantages: have to make all classes that use logging partial (although maybe that isn't so bad), and also I like the ext method syntax more
or do I just accumulate a static
Log
class for extension methods
I like the ext method here but there is no way to separate the logging methods and make them private, so I can see the code completion getting huge and naming collisions becoming a problem11 replies
✅ ɹoʇɐɹǝuǝƃ ǝɔɹnos lɐʇuǝɯǝɹɔuı uɐ ʇɐ ʎɹʇ ʇsɹıɟ
Had a go at writing an SG but I’m not very experienced with Roslyn so would appreciate some feedback. I’ve tried to apply the things I’ve overheard in the Roslyn file about enabling caching/incrementality but I’m not sure how to test it’s properly incremental.
Main sgen project: https://github.com/SapiensAnatis/Dawnshard/tree/1c04fb2944fc69dc706eb02aa8ab96fbf8eaf7c0/DragaliaAPI/DragaliaAPI.Shared.SourceGenerator
Sgen tests: https://github.com/SapiensAnatis/Dawnshard/tree/1c04fb2944fc69dc706eb02aa8ab96fbf8eaf7c0/DragaliaAPI/DragaliaAPI.Shared.SourceGenerator.Test
The goal of the sgen is to generate some deserialisation code for a static class, which is here https://github.com/SapiensAnatis/Dawnshard/blob/1c04fb2944fc69dc706eb02aa8ab96fbf8eaf7c0/DragaliaAPI/DragaliaAPI.Shared/MasterAsset/MasterAsset.cs
The code it actually generates is here: https://github.com/SapiensAnatis/Dawnshard/blob/1c04fb2944fc69dc706eb02aa8ab96fbf8eaf7c0/DragaliaAPI/DragaliaAPI.Shared/Generated/DragaliaAPI.Shared.SourceGenerator/DragaliaAPI.Shared.SourceGenerator.MasterAssetGenerator/MasterAsset.g.cs
10 replies
✅ Writing a source generator for this use case
I have some JSON data I want to load at startup, but image size has become a concern since in the published image these files are taking up 80MB. The general pattern I am using at the minute is
Note that there are about 100 such properties and I am interleaving the async calls to load them in parallel. Here the
MasterAssetData.LoadAsync
factory takes the JSON file which is an array and processes it as a dict:
I wanted to write a console app to run at build time, to convert all the json files to MessagePack with LZ4 compression. I initially used Roslyn to attempt to parse the contents of the MasterAsset class as a standalone cs file (so no symbol info) to build an association between json filepath -> type name
, e.g. CharaData.json -> CharaData
, so that I could first load up the JSON to deserialize it before re-serializing as binary, but I ran into a number of stumbling blocks trying to go from that type name to an actual Type
loaded via reflection, in the presence of things like generic types e.g. MasterAssetData<int, EventItem<BuildEventItem>>
.
I think it would be easier if I rethought this approach and wrote a source generator so that I had
which could then generate a property and LoadAsync
method for you, like in my second code block. This would then allow me in my console app to get the json path via reflection of the metadata of MasterAsset
rather than trying to parse the syntax tree for the function call, and it would save some typing when new entries are to be added. Downside is it feels a bit overkill to write an SG for just one class. I'd appreciate any thoughts, maybe the whole approach is horrific or maybe I'm on to something 🙂23 replies
Why is my SIMD code slower than the scalar version?
I wrote the following to learn more about simd - it tries to find a substring
https://paste.mod.gg/jswpvcpgoxgo/0
I ran a benchmark on my machine, which is avx512, compared against when it goes down the scalar path by setting DOTNET_EnableHWIntrinsic=0.
In my benchmark I have 2 paragraphs of Lorem Ipsum (1156 chars length) and a search string of a few words (47 chars length).
The vector512 benchmark takes approx 2.8us and the scalar benchmark takes 4.1us which seems like a fairly large difference and indicative that I’ve done something wrong.
Is there any more profiling I can use to work out what went wrong?
5 replies
✅ Am I using NumberFormatInfo properly?
I have a list of ca. 400 numbers which I want to convert to percentage strings as part of an endpoint. I know I will only ever want two decimal places or three decimal places. I was wondering about the impact of allocating a new
The results indicate caching is better but the end result after all the numbers in terms of allocs or nanoseconds saved seems unlikely to be significant (probably 217kB memory saved, or 12 microseconds faster). Is this premature optimization? OR is there a more idiomatic way to use NumberFormatInfo that I'm missing here?
NumberFormatInfo
each time so I whipped up some code:
The results indicate caching is better but the end result after all the numbers in terms of allocs or nanoseconds saved seems unlikely to be significant (probably 217kB memory saved, or 12 microseconds faster). Is this premature optimization? OR is there a more idiomatic way to use NumberFormatInfo that I'm missing here?
8 replies
✅ Renaming members across a project
I had some generated classes that looked like this:
where the properties were named in snake_case, because the property name drove what was serialized. I've since decided to re-scaffold them using my script more like
but now obviously everywhere I've used this type won't compile. I now have approximately 8300 errors in my project and I think a simple find and replace won't save me - what are some options to fix the errors? I could possibly write a script to convert all snake_case names to pascal case?
10 replies
✅ Is there a way you can check if an object’s equality operator will compare by reference?
I want to implement a data validation attribute like [UniqueValues] for ASP.NET model binding which will basically just call .Distinct() and check the count against the original list.
This however won’t work with plain classes, only value types, records, or classes that implement IEquatable. Is there a way I can check an
object
instance to see if it will be compared by reference, and if so throw an exception?13 replies
✅ Can’t disable warnings in generated code
My warnings as errors pipeline is failing because of generated code ending with .g.cs which doesn’t have xml comments.
I added the following to the editorconfig at the root of my solution:
But the warnings keep appearing. Is this not a valid selector for editorconfig?
35 replies
MSBuild task that shouldn't run in CI
I've got an MSBuild task which I don't want to run in my pipelines. So I wrote the following:
because according to github, the
GITHUB_ACTIONS
env var should always be set by default in CI: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
However, it still seems to run in my pipelines judging by the output. Am I doing something wrong?2 replies
Converting from a string to a generic method invocation
Looking for design patterns to help solve this problem I’m having at work. The situation is that we have a URL like GET /entities/<userid>/<entity type> where entity type is a string, and we want to fetch the entities of that type belonging to the current user.
Normally I would just use a switch case to go from eg entitytype = “someentity” => entitiesService.GetEntities<SomeEntity>(). But my tech lead insists that new entity types should be automatically supported without code changes to this endpoint because he thinks it will be forgotten.
I’ve landed on a solution using reflection to grab the types deriving from my base Entity class and build a dict of (string, Type), then using reflection to get the method info of GetEntities and use MakeGenericMethod with the type from the dict, but am not too pleased with it.
I’m considering the following alternatives:
- source generators, seemed like a lot of code to generate 1 switch case
- using reflection in the testing to make the pipeline fail if another dev forgets to update the endpoint
But I’d like to know if there are any other solutions people can think of / thoughts on some of the existing options
12 replies
❔ NavigationManager: TaskCancelledException
I've got an OAuth login button:
And it seems I get quite a few errors from the deployment:
I found a github issue with something similar which I now can't find again, but the root cause there was using Task.Result. However I am not using that anywhere so I'm not sure what is happening here, any suggestions would be appreciated
Navigation failed when changing the location to https://baas.lukefz.xyz/custom/thirdparty/auth[...]
with an inner exception ofI found a github issue with something similar which I now can't find again, but the root cause there was using Task.Result. However I am not using that anywhere so I'm not sure what is happening here, any suggestions would be appreciated
11 replies
❔ ASP.NET Core Persist Task between requests
I am programming an API and one of my endpoints needs to do a database operation, but it will take a long time, and the result is not actually needed until a different endpoint is called. I would like to queue the Task on the first endpoint and return a 202 Accepted, then only have to await the task (if it has not already completed) on the other endpoint.
I’m not sure what the best way to do this would be. I could have a static dictionary of tasks keyed by users stored in a service, but this seems naive. I’ve heard about background workers but this is an on-demand thing so I’m not sure if that’s appropriate either as I get the feeling they’re for cron-type things. Any advice would be appreciated.
195 replies