microsoft / microsoft/aspire

`IProjectMetadata` abstraction should be generalized outside of `Aspire`

Open
#11,606 1 comment 0 reactions 0 assignees View on GitHub
area-app-model
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Is your feature request related to a problem? Please describe the problem.

Aspire has this nice `IProjectMetadata`-based "automation" that uses a source generator to create "project metadata" classes for all projects referenced in the AppHost project, which are then used to reference projects during runtime when configuring various modules/connections/etc.

This works great in Aspire itself, but I believe this concept should be made more general-purpose.

In many applications today, there is a need to "reference a project" in code. In most cases, this is done by grabbing a "token type" from that project, and then accessing its `Assembly` property from there.

This approach is used today in _many_ different frameworks. Here are a few:

- `AutoMapper`, for registering all mappers found "in assemblies of types"
- `MediatR`, same as `AutoMapper`
- `FluentValidation`, to register all validator implementations found "in assemblies of types"
- `Scrutor`, also has type/assembly-based scanning capabilities
- `EntityFrameworkCore` for registering all `IEntityTypeConfiguration` instances in an assembly
- etc...

Grabbing a random type from `Assembly` X that "represents that project" is arbitrary and sometimes unintuitive. People have come up with all sorts of workarounds to this problem, the most well-known being creating a "marker type" inside of each project that is exclusively used for that particular purpose that has a name that makes that more clear, for example, instead of referencing `SomeRandomType` from `ProjectA`, it references a `ProjectAMarker` type.

This is a very similar problem that Aspire has "solved" in its context: having information about a "project as a whole" during runtime.

### Describe the solution you'd like

I think it would be beneficial to the ecosystem if such a concept was abstracted at a lower-level library that could be used by higher level libraries and tools to create extensions that would target this "project abstraction". Take `AutoMapper` for example, which could now provide an API that would look like this:

```csharp
services.AddAutoMapper(opt => opt.AddMaps(Projects.ProjectA, Projects.ProjectB));
```

All that would be needed for this to work is that the source generator included the `Assembly` of each project in the generation.

I believe the best place to move this concept from Aspire to would be the `Microsoft.Extensions.Hosting.Abstractions` package.

### Additional context

This is a very general problem that has no built-in solution today. Keeping custom marker types adds boilerplate and is nonstandard. The language/framework provides no support for referencing "a project", even though that's exactly the developer intent when using all of those methods in the libraries I shared earlier: there is clearly an abstraction missing here.

I believe this is a good opportunity to bring a nicer "first-class" experience to all application types of something that Aspire did, but that could be used for more use-cases other than Aspire itself.

This more "general-purpose" version of Aspire's "Projects" autogenerated namespace would also probably require an implementation for "the current project", something like `Projects.This` or similar.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.