Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Solution] Nullable attributes are not discovered in WPF projects #11

Closed
chucker opened this issue Jun 25, 2020 · 7 comments
Closed

[Solution] Nullable attributes are not discovered in WPF projects #11

chucker opened this issue Jun 25, 2020 · 7 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@chucker
Copy link

chucker commented Jun 25, 2020

I have a relatively complex solution with lots of legacy stuff, but I did manage to modernize some of the assemblies to the Sdk style and PackageReference instead of packages.config. I can add your NuGet package and then write code like this, in .NET Framework 4.7.2:

    public bool TryGetExistingFavorite(ContactRecord record, [NotNullWhen(true)] out Favorite? favorite)
    {
        favorite = _Favorites.FirstOrDefault(f => f.CID == record.ID);

        return favorite != null;
    }

This looks great during design-time builds. But when I actually do a full build, I get an error that the attributes can't be found:

1>…path…\Favorites\FavoritesRepository.cs(108,68,108,79): error CS0246: The type or namespace name 'NotNullWhenAttribute' could not be found (are you missing a using directive or an assembly reference?)
1>…path…\Favorites\FavoritesRepository.cs(108,68,108,79): error CS0246: The type or namespace name 'NotNullWhen' could not be found (are you missing a using directive or an assembly reference?)
1>Done building project "MyProject_hh54oelh_wpftmp.csproj" -- FAILED.

I've tried both a regular reference like so:

    <PackageReference Include="Nullable" Version="1.2.1" />

And the adjusted one from the README:

    <PackageReference Include="Nullable" Version="1.2.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

I think the …**wpftmp**.csproj portion may be a clue. However, with a test project that also contains WPF, I wasn't able to reproduce the issue.

@manuelroemer
Copy link
Owner

manuelroemer commented Jun 25, 2020

Hey, sorry to hear that you are having this issue. I've done some testing/browsing and can reproduce it locally (Project Download Here - open MainWindow.xaml.cs for the method triggering the problem).

It seems that the issue arises from the way WPF projects are compiled. There are some GitHub issues which may provide more insights into why the problem occurs:

To summarize the issue: During the build, WPF creates a temporary project (for compiling XAML, I believe). In this temporary project, the NuGet packages are not imported, hence the build error that the attributes could not be found. This problem also affects other source code only packages similar to Nullable.

Unfortunately I am currently unsure how this might be fixed. Maybe there's a chance to develop a workaround, but ultimately, the issue should be fixed at the root, i.e. in the WPF build process.

Nontheless, I don't want to leave you hanging - maybe there are other ways to solve your problem until a real solution arrives for this issue. Here are some suggestions:

  1. You might want to have a look at the https://github.com/tunnelvisionlabs/ReferenceAssemblyAnnotator project. They also offer a way to include the nullable attributes in a legacy projects. I haven't tried, but perhaps their approach works better?
  2. This is nasty after all the work you have put into upgrading your project, but maybe you can try going back to a non-SDK style project. Again, not sure if this solves the problem, but it might be worth a try.
  3. [The Approach I'd Use] You could not use the Nullable package for WPF projects and instead manually define the attributes using a shared project. This should work with any project configuration. This is also not ideal since you lose automatic package updates, but realistically, there won't be many since the .NET team doesn't periodically create new attributes. If anything, Add support for [MemberNotNull] and [MemberNotNullWhen] #9 will be added soon-ish, but that's it for the next year(s).

If you (or anyone else) has any ideas how the problem can be worked around from the perspective of the Nullable package, feel free to share your ideas!

@manuelroemer manuelroemer added bug Something isn't working help wanted Extra attention is needed labels Jun 25, 2020
@manuelroemer manuelroemer pinned this issue Jun 25, 2020
@manuelroemer manuelroemer changed the title Compile fails with (some) Sdk-style .NET 4.7.2 projects? The Nullable package targets are not importet in the temporary SDK-Style WPF project builds, leading to failed compilations. Jun 25, 2020
@manuelroemer manuelroemer changed the title The Nullable package targets are not importet in the temporary SDK-Style WPF project builds, leading to failed compilations. The Nullable package targets are not imported in the temporary SDK-Style WPF project builds, leading to failed compilations. Jun 25, 2020
@chucker
Copy link
Author

chucker commented Jul 6, 2020

(Thanks for your answer. Will look into those!)

@chucker
Copy link
Author

chucker commented Jul 27, 2020

So, I tried approach 1, and… they have a similar issue (which sounds… more fixable?):

error CS0122: 'NotNullWhenAttribute' is inaccessible due to its protection level

It looks like someone else already discovered that: tunnelvisionlabs/ReferenceAssemblyAnnotator#81

2 seems… not fun.

I might be able to live with 3. But now I'm tempted by the additional features in the project mentioned in 1…

@manuelroemer
Copy link
Owner

Alright, thanks for testing! I'm not sure about the CS0122 being more fixable. On first sight, the only solution seems to be to make the attributes public, but that should never be done, because it will quickly lead to naming conflicts when another referencing project also declares these attributes. Hence why they are declared as internal. (The only exception where public attributes are okay-ish is a project which is not published - there you have full control over it.)

now I'm tempted by the additional features in the project mentioned in 1…

I totally recommend using ReferenceAssemblyAnnotator instead of Nullable then! It is indeed an awesome project.
Nullable is kept lightweight on purpose, i.e. I only want to provide the attributes and nothing else. Using an analogy, Nullable is, so to say, the lightweight code editor while ReferenceAssemblyAnnotator is a fully featured IDE - sometimes the first is enough, but for larger tasks/projects, the additional features are preferable. 😄

If they cannot fix the CS0122 error which you posted above, you might even be able to combine ReferenceAssemblyAnnotator with Option 3 above, i.e. you could manually create the NullableAttributes.cs file in your project to have access to the attributes and disable RAA's attribute generation in your cs project: <GenerateNullableAttributes>false</GenerateNullableAttributes>. Not tested, but this might work just fine for your project.

@chucker
Copy link
Author

chucker commented Aug 10, 2020

Nullable is kept lightweight on purpose, i.e. I only want to provide the attributes and nothing else.

Yeah, makes sense to me. This is the one I ran into, but I think I want the "IDE" approach for my use case.

They did figure out a fix, which appears to work for me (once I explicitly set UseWPF). That fix may actually help you as well. It appears _GeneratedCodeFiles is a variable used by the WinFX (i.e. WPF) tasks.

@AArnott
Copy link

AArnott commented Feb 19, 2021

Check out microsoft/CsWin32#7 for a discussion of this and how the latest .NET SDK fixed their bug so Nullable should Just Work going forward.

@manuelroemer
Copy link
Owner

That sounds amazing! I’ll close this as resolved then and make a mental note to document this in the README so that it is immediately clear to WPF users!

@manuelroemer manuelroemer pinned this issue Apr 14, 2021
@manuelroemer manuelroemer changed the title The Nullable package targets are not imported in the temporary SDK-Style WPF project builds, leading to failed compilations. [Solution] Nullable attributes are not discovered in WPF projects Apr 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants