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

SystemResources depends on DependencyService #24216

Closed
dansiegel opened this issue Aug 13, 2024 · 3 comments · Fixed by #26010
Closed

SystemResources depends on DependencyService #24216

dansiegel opened this issue Aug 13, 2024 · 3 comments · Fixed by #26010
Labels
area-testing Unit tests, device tests migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert t/bug Something isn't working

Comments

@dansiegel
Copy link
Contributor

Description

When trying to run unit tests and using the MauiAppBuilder after resolving the Application and while creating the Window a NullReferenceException is encountered.

  Message: 
System.NullReferenceException : Object reference not set to an instance of an object.

  Stack Trace: 
<.ctor>b__7_0()
Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
Lazy`1.CreateValue()
Application.get_SystemResources()
ResourcesExtensions.GetMergedResources(IElementDefinition element)
Element.SetParent(Element value)
Element.OnChildAdded(Element child)
Element.AddLogicalChild(Element element)
Application.AddWindow(Window window)
IApplication.CreateWindow(IActivationState activationState)

This error is a result of the following lines of code:

#pragma warning disable CS0612 // Type or member is obsolete
_systemResources = new Lazy<IResourceDictionary>(() =>
{
var systemResources = DependencyService.Get<ISystemResourcesProvider>().GetSystemResources();
systemResources.ValuesChanged += OnParentResourcesChanged;
return systemResources;
});
#pragma warning restore CS0612 // Type or member is obsolete

This isn't initially obvious as to either the problem or the solution as it requires implementing "Obsolete" code in order for a very basic scenario to work in a Unit Test.

Steps to Reproduce

var mauiBuilder = MauiApp.CreateBuilder()
    .UseMauiApp<Application>();
mauiBuilder.Services.AddTransient<IWindowCreator, WindowCreator()
    .AddTransient<TestPage>();

var mauiApp = mauiBuilder.Build();
var app = mauiApp.Services.GetRequiredService<IApplication>();
var activationState = new ActivationState(new MauiContext(mauiApp.Services));
var window = app.CreateWindow(activationState);

private record WindowCreator(TestPage Page) : IWindowCreator
{
    public Window CreateWindow(Application app, IActivationState? activationState) => new Window(Page);
}

public class TestPage : ContentPage
{
    public TestPage()
    {
        Title = nameof(TestPage);
        Content = new Label { Text = "Unit Tests" };
    }
}

Link to public reproduction project repository

No response

Version with bug

8.0.80 SR8

Is this a regression from previous behavior?

Yes, this used to work in Xamarin.Forms

Last version that worked well

Unknown/Other

Affected platforms

Other (Tizen, Linux, etc. not supported by Microsoft directly)

Affected platform versions

No response

Did you find any workaround?

While this technically does work... it shouldn't be something that is needed just to run Unit Tests.

#pragma warning disable CS0612 // Type or member is obsolete
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Internals;
using Prism.Ioc.Tests.Mocks;

[assembly: Dependency(typeof(MockResourcesProvider))]
[assembly: Dependency(typeof(MockFontNamedSizeService))]

namespace Prism.Ioc.Tests.Mocks;

[Obsolete]
internal class MockResourcesProvider : ISystemResourcesProvider
{
    public IResourceDictionary GetSystemResources()
    {
        var dictionary = new ResourceDictionary();
        Style style;
        style = new Style(typeof(Label));
        dictionary[Device.Styles.BodyStyleKey] = style;

        style = new Style(typeof(Label));
        style.Setters.Add(Label.FontSizeProperty, 50);
        dictionary[Device.Styles.TitleStyleKey] = style;

        style = new Style(typeof(Label));
        style.Setters.Add(Label.FontSizeProperty, 40);
        dictionary[Device.Styles.SubtitleStyleKey] = style;

        style = new Style(typeof(Label));
        style.Setters.Add(Label.FontSizeProperty, 30);
        dictionary[Device.Styles.CaptionStyleKey] = style;

        style = new Style(typeof(Label));
        style.Setters.Add(Label.FontSizeProperty, 20);
        dictionary[Device.Styles.ListItemTextStyleKey] = style;

        style = new Style(typeof(Label));
        style.Setters.Add(Label.FontSizeProperty, 10);
        dictionary[Device.Styles.ListItemDetailTextStyleKey] = style;

        return dictionary;
    }
}

[Obsolete]
public class MockFontNamedSizeService : IFontNamedSizeService
{
    public double GetNamedSize(NamedSize size, Type targetElement, bool useOldSizes)
    {
        return size switch
        {
            NamedSize.Default => 12,// new MockFontManager().DefaultFontSize,
            NamedSize.Micro => (double)4,
            NamedSize.Small => (double)8,
            NamedSize.Medium => (double)12,
            NamedSize.Large => (double)16,
            _ => throw new ArgumentOutOfRangeException(nameof(size)),
        };
    }
}
#pragma warning restore CS0612 // Type or member is obsolete

Relevant log output

No response

@dansiegel dansiegel added the t/bug Something isn't working label Aug 13, 2024
Copy link
Contributor

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

@samhouts samhouts added the migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert label Aug 19, 2024
@samhouts samhouts added the area-testing Unit tests, device tests label Aug 28, 2024
@kevinxufei
Copy link

@dansiegel Could you provide us with a sample project so we can investigate it further? Looking forward to your reply!

@mattleibow
Copy link
Member

Hmmm, this stuff....

I think the issue is that we should not be using the ISystemResourcesProvider at all. That type is marked as obsolete, so we should probably have a "try get it, otherwise don't do anything".

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-testing Unit tests, device tests migration-compatibility Xamarin.Forms to .NET MAUI Migration, Upgrade Assistant, Try-Convert t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants