andrewlock / StronglyTypedId

A Rosyln-powered generator for strongly-typed IDs
MIT License
1.52k stars 79 forks source link

CS0436 Warning #38

Closed kfrancis closed 2 years ago

kfrancis commented 3 years ago

When defining strong ids in a project and a child project which references the parent, we're seeing new CS0436 errors like this:

19>C:\Users\kfrancis\Projects\supercoolproject\aspnet-core\test\supercoolproject.Web.Tests\StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdDefaultsAttribute.cs(24,62,24,92): warning CS0436: The type 'StronglyTypedIdImplementations' in 'StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdImplementations.cs' conflicts with the imported type 'StronglyTypedIdImplementations' in 'supercoolproject.Application.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdImplementations.cs'. 19>C:\Users\kfrancis\Projects\supercoolproject\aspnet-core\test\supercoolproject.Web.Tests\StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdAttribute.cs(25,62,25,92): warning CS0436: The type 'StronglyTypedIdImplementations' in 'StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdImplementations.cs' conflicts with the imported type 'StronglyTypedIdImplementations' in 'supercoolproject.Application.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'StronglyTypedIds\StronglyTypedIds.StronglyTypedIdGenerator\StronglyTypedIdImplementations.cs'.

kfrancis commented 3 years ago

We're using the new 1.0.0-beta01

andrewlock commented 3 years ago

Thanks for trying it out @kfrancis . This is happening because the attribute and enums are added as source code to the project. Currently they're added as public; as they're added to both projects, that's where the conflict comes from.

I'm not 100% sure the best way to fix this 🤔 The "simple" approach is to make them internal instead, so they don't conflict between projects. However, this will still have issues if you have an [InternalsVisibleTo] attribute, which makes me wonder if a different approach should be used. For example, the attributes and enums could be moved to an external lib, so the types are shared. I wanted to avoid that so that it wouldn't be included in the build output, but I think there might not be any other option.

In the mean time, I've put up an update that converts the types to internal, which should unblock you, but I think the assembly approach is probably the "correct" approach

Mertsch commented 2 years ago

Hey @andrewlock I am having exactly the same issue. The thing is, I already added the reference to StronglyTypedIds and the ID itself to a base project and the ID is generated in all dependent projects anyway. I think this should not happen and only be generated in the base project/assembly.

andrewlock commented 2 years ago

@Mertsch could you clarify, are you using the latest beta version (beta2)?

Mertsch commented 2 years ago

@andrewlock Yes, I am using beta2. The issue arises only with [assembly: InternalsVisibleTo("TestProject.Tests")] 2021-09-22 10-30-25 devenv

But the Type TestId could just be used as a normal shared struct in all projects, without each project implementing the same TestId.

andrewlock commented 2 years ago

Ah, yes, as mentioned above, that problem arises when you have the internals visible to and address referencing the library in both projects.

To be clear, the ID isn't implemented in both projects, the attributes and enums are added to each project as source code, hence the duplicate definition.

I took that approach a) for simplicity and b) to avoid adding extra DLLs to your build output. Unfortunately I think the only option is to add the extra DLL containing the attribute etc, which is rather annoying. Ideally I'd like to remove the attribute from there output but I don't think that's possible using source generators

Mertsch commented 2 years ago

@andrewlock Ah, now I get it! I did not understand the attributes part. As an idea: How about making an option to the attribute itself like AttributeStrategy with IncludeAsCode (Internal, all projects), IncludeAsCodeInProjectsWhichUseThem (public?), IncludeViaPackage?

Also I noticed that Newtonsoft is the default serializer and would suggest to go with SystemTextJson, as the first thing you get are build errors due to a missing serializer package when starting fresh. And with SystemTextJson you are probably going to have the package available due to .NET 5 and 6.

kfrancis commented 2 years ago

Thanks for trying it out @kfrancis . This is happening because the attribute and enums are added as source code to the project. Currently they're added as public; as they're added to both projects, that's where the conflict comes from.

I'm not 100% sure the best way to fix this 🤔 The "simple" approach is to make them internal instead, so they don't conflict between projects. However, this will still have issues if you have an [InternalsVisibleTo] attribute, which makes me wonder if a different approach should be used. For example, the attributes and enums could be moved to an external lib, so the types are shared. I wanted to avoid that so that it wouldn't be included in the build output, but I think there might not be any other option.

In the mean time, I've put up an update that converts the types to internal, which should unblock you, but I think the assembly approach is probably the "correct" approach

Much better here. Thank you!

andrewlock commented 2 years ago

@Mertsch I've taken a similar approach to your suggestion in the latest beta. By default, you just add the source generator as usual and the attributes are added to the compilation. But if you run into [InternalsVisibleTo] issues, you can work around it by adding the StronglyTypedId.Attributes package, as I describe in the README.

Hopefully that should solve this issue for good, so I'll close this for now