I need to create code by the IIncrementalGenerator
in at least two projects which are referring to the same library that references the SourceCodeGenerator
project.
My solution, for further clarification:
MySolution
|->DesktopApp
| |->ref:Library
|
|->Library
| |->ref:SourceGenerator
|
|->WebApi
| |->ref:Library
|
|->SourceGenerator
In the library, I define Interfaces for all objects I use across my application, many properties I define in the interface are Ids which I mark by an attribute where I head the IType
of the underlying object.
The attribute:
[System.AttributeUsage(System.AttributeTargets.Property)]
public class NavigationPropertyAttribute : System.Attribute
{
public System.Type NavigationPropertyType { get; }
public NavigationPropertyAttribute(System.Type type) => NavigationPropertyType = type;
}
This is how such an Interface looks like:
public interface IFoo
{
int Id { get; set; }
[NavigationProperty(typeof(IBar))]
int BarId { get; set; }
[NavigationProperty(typeof(IFoo))]
int ParentId { get; set; }
[NavigationProperty(typeof(IFoo))]
int ChildId { get; set; }
}
In both projects, one is a desktop application, the other is a Web API using EF Core, I have partial classes implementing these interfaces.
namespace IGTryout.Main;
public partial class Foo : IFoo
{
public int Id { get; set; }
public int BarId { get; set; }
public int ParentId { get; set; }
public int ChildId { get; set; }
}
what I need now, and where I'm struggling with, is using the IIncrementalGenerator
to create a partial class with properties based on the Id
, Name
and the Type
from the NavigationPropertyAttribute
.
public partial class Foo
{
private Bar bar;
public Bar Bar => bar ??= GetValue<Bar>();
private Foo parent;
public Foo Parent => parent ??= GetValue<Foo>();
private Foo child;
public Foo Child => child ??= GetValue<Foo>();
}
(GetValue<T>()
is an extension which gets the [CallerMemberName]
, resolves the matching Id
via reflection and returns the object from cache by resolving it by the type and id)
In the Web API project, I'm also implementing the interfaces, yet, creating the NavigationProperties
the common way
Foo { get; set; }
to fullfill EF Core's needs, also I'm creating the InversePropertyCollection
in the related object for having the foreign keys set as needed by EF Core.
All of this is done, so I can use the interfaces as TransportObject
with as little overhead as possible when sending them from the Web API to my desktop application and reverse.
Now to the problem I have:
to trigger all changes done to the interfaces, I reference my SourceCodeGenerator
project from the library project, but by doing so, I can not find any opportunity to create the code inside the Web API assembly or the desktop app assembly.
I did solve this problem before by using the common SourceGenerator
and referencing the SourceCodeGenerator
project by both, the desktop app and the Web API, and accessing the interfaces inside my library project by calling the ReferencedAssemblySymbols
of my compilations SourceModule
and iterating over to the relevant project, since it is referenced by both, but this rather hacky solution is not possible, since would loose all the possibilities, which led me to switch to the IIncrementalGenerator
in the first place.