Maui: [Bug] MCT001 doesn't recognize initialization in a library

Description

Update to the latest CommunityToolkit.Maui Version=“1.1.0” and my project now fails build due to error:

MCT001: .UseMauiCommunityToolkit() must be chained to .UseMauiApp<T>()

While I like the fact that the library is looking over my shoulder to ensure I’m calling this, it really should be written to understand the dependency chain when looking for the call to the initialization routine. My software architecture is loosely coupled allowing libraries of functionality to be added individually to the main/exe project. Anytime a individual library is added, a corresponding fluent init method is called (just as you’re doing with the toolkit). So in my situation, one of my UI libraries takes advantage of the Toolkit, and thus its MauiApp Fluent Initialization method calls .UseMauiCommunityToolkit() directly. My main/exe project therefore calls the .UseMauiCommunityToolkit() method indirectly. However, because your initialization test is transient, it is failing the top level project when in fact it should be stopping at the library level.

This also brings up the question - can the .UseMauiCommunityToolkit() method be called multiple times (multiple decoupled libraries in a project use the toolkit) without undesired side effects such as service registrations, etc.

Steps to Reproduce

  1. Create a MAUI app that references a MAUI Library.
  2. Inside that library, add a reference to CommunityToolkit.Maui Version=“1.1.0”
  3. Call .UseMauiCommunityToolkit() from inside the Library
  4. Build and see error

Expected Behavior

No build failure

Actual Behavior

build failure

Basic Information

  • Version with issue: 1.1.0
  • Last known good version: 1.0.0

Workaround

Add MCT001 to Suppress specific warnings in project Build>Errors and Warnings section

Demo project

I created this project with Microsoft Visual Studio Professional 2022 (64-bit) - Preview Version 17.3.0 Preview 4.0

MauiAppInitBug.zip

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (8 by maintainers)

Most upvoted comments

@brminnick I think we can close this issue, and move it to a discussion (if still needed). Pedro already solved an issue when comments are set in the initialization, which I know it was not part of the original issue reported. However, I think this is a requested feature to support MCT in a library and not an actual issue, and can be discussed first, so all can come up with ideas about which can be the best implementation for including MCT in a library (if actually, it is needed for decoupled environments).

Hey Gang! This is a challenging problem to solve. Implementing Roslyn Analyzers and Code Fixes is a new challenge for all C# developers, and I promise you that if I knew how to solve this Issue I would’ve implemented it already, just like I’m sure you, @bakerhillpins, would’ve submitted a PR if you knew the solution as well.

We will be keeping this Analyzer because UseMauiCommunityToolkit() is required for our library to work properly.

@bakerhillpins we are aware of this Issue. It is on our radar. If you are able to update the Analyzer to solve it, please submit a PR.

Please keep this conversation scoped to solutions to the Issue.

@bakerhillpins if in your lib, you don’t call the UseMauiCommunityToolkit and the application developer call that method on the MauiProgram class, will the lib work? Or is it required to call our initializer inside the lib’s init method?

Yes it will work that way but that brakes the encapsulation/isolation of the application component library (which references the toolkit) by forcing an unnecessary dependency between the application and the toolkit (which is only necessary for the component Library). The application that references the component Library shouldn’t have to manage implementation details of the reference. This is the same reason a developer would specify an Interface/API publicly and hide the details of the implementation behind it. No consumer of any API should have to take implementation dependencies directly in order to use the Interface/API. This is a basic software design principle. Proper test design would also make this situation evident.

Regardless, the MCT001 code is INCORRECTLY reporting an error. This is a false positive and should never be fixed by disabling the error.

For a bit more context, at least for me, never thought that lib. authors will reference our toolkit, so I never account this scenario in the analyzer.

Might I suggest reading up on software architecture design then, starting with this document: The Onion Architecture These are fundamental principles of design, allowing for reuse (This is a Library after all and should be designed for reuse). This is a great starting piece and you can search and build from there. Any other documentation on Interface/API (Not User Interface Design although it is related) or design for testing is also going to discuss the subject.

I disagree this adds little value, when this came public on Twitter other lib authors thought this a good idea and want to implement it on their projects. Isn’t because you face an issue this adds little value (; , let’s think a workaround for now, that way you’re not blocked and later think in how we can solve the issue for libs that reference our toolkit.

It’s nice that feedback was solicited for the idea. However, Twitter is a great place for opinions but rarely anything else. Was there a discussion raised here, in the project, where users could discuss the merits? I was unable to locate one. Microsoft themselves follow this model for good reason. The value of this feature is not subjective, it’s easy to determine. It’s surface area is directly correlated to the number of problems it solves for the user of the Library.

  • In this case it solves exactly ONE problem. The developer forgot to call the Initialization method.
  • When could this error occur. This is also simple. It happens EARLY in the development/use cycle because it’s necessary for the Library to function. It is unlikely that the developer will spend months coding a solution that uses the library before trying any individual feature out thus the code to evaluate is small.
  • Is it likely to reoccur. No, this is a startup time issue and that code is unlikely to be modified as the library user adds more features which leverage the library.

Thus the surface area where this issue could effect an end user of the library is LIMITED.

The complexity of this problem is HIGH since the number of permutations for a valid call to the initialization method is HIGH and requires a significant amount of complex code to cover the corner cases. This fact that you’ve already suggested overriding the error as the fix suggests that the solution is overly burdensome on the library developers and you’re trying to ignore it.

Low surface area and High complexity suggests that this has limited impact for users and high impact on library maintenance. IMHO this feature should be removed.

Ooh i see now

@bijington yes, we can add an attribute and look for that. That should work similarly to how the analyzer detects Obsolete attributes in the code base.

@bakerhillpins this isn’t a Source Generator issue and a Roslyn Analyzer issue. We don’t want to cover all scenarios, if the user is doing something fancy he/she can disable our analyzer easily, as you can see in the screenshot below: image

@bakerhillpins I’m sorry, but I’m guided by samples. You provide a snippet and I confirmed that the issue happens in that case, so I fixed that. Didn’t pay attention to the lib part.