dimanche 5 mars 2023

How to get list of attributes value from solution in C# other than by reflection?

I have a large solution with multiple projects, but for simplicity let's shrink it down to three projects:

  1. Application.Client (it has a reference to Application.Common project)
  2. Application.Common
  3. Application.SourceGenerator

Application.Client

This project has interfaces with specific custom attribute to each method

public class ProcessActionAttribute : Attribute
{
    public ProcessActionAttribute(string guid)
    {
        Value = guid;
    }

    public string Value { get; }
}

Example:

public interface IProcessService
{
    [ProcessAction("2e145a71-dfeb-4c40-ae3f-d0ff5c45d7f6")]
    void ProcessItem();

    [ProcessAction("9795d060-962a-4790-bea0-9380a6ffd3eb")]
    void CreateItem();
}

Application.SourceGenerator

Generates a class ProcessActionGuidProvider in Application.Client with a static dictionary of all methods with their guids extracted from ProcessActionAttribute.

Application.Common

The idea of this class library is to be referenced and used by other libraries to get list of all ProcessActionAttribute guids of all interfaces methods in the solution.

Since Application.Client references Application.Common I cannot create circular reference by referencing Application.Client in Application.Common.

What do I want to achieve?

My goal is to use the class generated by source generator from Application.Client (and from more projects in the solution) in Application.Common.

Issues on the way

My initial idea was to implement in source generator that extracts guids from Application.Client but it also adds the ProcessActionGuidProvider class to the same project. Once I add another project to be analyzed, it would create yet another provider in another project.

Another idea that I had before that was to use reflection to do that and keep the dictionary in cache to increase performance. This worked nicely, but application slowed down and tests were going slow as hell.

Is there anything else other than reflection and source generator that I could use?

Possible fix 1

The easiest way to fix it would be to move all interfaces from Application.Client to Application.Common and use source generator to generate the class ProcessActionGuidProvider in Application.Common.

Unfortunately, for undisclosed reasons I cannot do that. I have to find a workaround for it.

Possible fix 2

I could also just create a static method that does the same job as SourceGenerator using reflection, but the performance is very slow due to how large this solution is.





Aucun commentaire:

Enregistrer un commentaire