-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
MarkupExtension: IRootObjectProvider not available in release mode #16881
Comments
Hi @loop8ack. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time. |
I have created the following repository for reproduction: Maui.Issue16881.Reproduction Just run it and look at the output. |
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process. |
What platform does this happens? Any thoughts @StephaneDelcroix ? |
Verified this on Visual Studio Enterprise 17.8.0 Preview 1.0 using below Project (.NET 8.0), This issue repro on Windows 11 and Android 13.0-API33. |
What's the status on fixing this? I have this issue on version 8.0.100. |
I have encountered the same issue when working on a similar project as @SirJohnK in Maui 8.0.40 |
Seems like the public class XamlServiceProvider : IServiceProvider
{
readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
internal XamlServiceProvider(INode node, HydrationContext context)
{
if (context != null && node != null && node.Parent != null && context.Values.TryGetValue(node.Parent, out object targetObject))
IProvideValueTarget = new XamlValueTargetProvider(targetObject, node, context, null);
if (context != null)
IRootObjectProvider = new XamlRootObjectProvider(context.RootElement); Any thoughts on this @StephaneDelcroix ? |
Found a workaround until this is fixed. Root object can be retrieved from Made this extension method: public static object? GetRootObject(this IProvideValueTarget provideValueTarget)
{
//Attemp to get the root object from the provided value target
var pvtType = provideValueTarget?.GetType();
var parentsInfo = pvtType?.GetProperty("Microsoft.Maui.Controls.Xaml.IProvideParentValues.ParentObjects", BindingFlags.NonPublic | BindingFlags.Instance);
var parents = parentsInfo?.GetValue(provideValueTarget) as IEnumerable<object>;
return parents?.LastOrDefault();
} |
Seeing this now that we're trying to finally get our app out! |
Here's where this all breaks down for us. /// <summary>
/// The base localization manager.
/// </summary>
[ContentProperty(nameof(Text))]
public class TranslateExtension : IMarkupExtension<BindingBase>
{
public object? BindingContext { get; set; }
public IValueConverter? Converter { get; set; }
public object? ConverterParameter { get; set; }
public string? StringFormat { get; set; }
/// <summary>
/// The text for localization.
/// </summary>
public string Text { get; set; } = string.Empty;
public virtual string GetResourceString(IStringLocalizer<CabMdResource> loc)
{
ArgumentNullException.ThrowIfNull(loc);
return loc[Text];
}
/// <summary>
/// Gets the localization text.
/// </summary>
/// <param name="serviceProvider">The service provider.</param>
public BindingBase ProvideValue(IServiceProvider serviceProvider)
{
// Try to get IRootObjectProvider; return the text itself if it's missing
var rootObjectProvider = serviceProvider.GetService<IRootObjectProvider>();
if (rootObjectProvider == null)
{
// If IRootObjectProvider is unavailable, fallback to returning a simple binding to the Text property
return new Binding
{
Mode = BindingMode.OneWay,
Path = Text
};
}
if (rootObjectProvider.RootObject is not BindableObject bindableObject || bindableObject.BindingContext is not ViewModelBase viewModelBase)
{
return new Binding
{
Mode = BindingMode.OneWay,
Path = Text
};
}
var localizationResourceManager = viewModelBase.L;
return new Binding
{
Mode = BindingMode.OneWay,
Path = $"[{Text}]",
Source = localizationResourceManager,
StringFormat = StringFormat,
Converter = Converter,
ConverterParameter = ConverterParameter
};
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
}
} I've tried that workaround @SirJohnK, but I'm not sure how it applies in this context. Also, moving to your lib looks like so much work for us .. coming from an abp.io/mvvm scenario. |
IProvideValueTarget is a service that you can receive from the IServiceProvider. var rootObjectProvider = serviceProvider.GetService<IRootObjectProvider>();
var rootObject = rootObjectProvider == null
? serviceProvider.GetService<IProvideValueTarget>()?.GetRootObject()
: rootObjectProvider.RootObject; Heads up: I wrote this in the browser and have not tested it. |
@loop8ack, was about to say exactly that!👍 By the way, the latest prerelease version of my library is on NuGet and includes some really neat features, if I say so myself. 😄 (where this extension method is used for page specific resources 😅) |
In .NET 9 the Has anyone figured out how to get this to work in combination with the attribute? |
@StephaneDelcroix , can you PLEASE comment on this!?
|
Xaml inflator differs from Release and Debug, that's why it behave differently. IXamlRootObjectProvider was never available with XamlC inflator (Release builds) the purpose of IXamlRootObjectProvider is to help with built-in markup extension and was never meant to be used publicly. not sure why one would need it... |
@StephaneDelcroix , thanks for commenting!
Thank for your great work! 👍 /Regards Johan |
I found a .NET 9 solution!!! 😄 Add BOTH
With this, my Really unfortunate that we can't just get
/Johan |
Description
The ServiceProvider passed to the ProvideValue method of a MarkupExtension returns an IRootObjectProvider in debug mode, but not in release mode.
I have been able to reproduce it with the following versions:
Steps to Reproduce
Create a new MAUI project and use the following code:
Output in debug mode: true
Output in release mode: false
All other services are available in both debug and release mode
Link to public reproduction project repository
Maui.Issue16881.Reproduction
Version with bug
8.0.0-preview.7.8842
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
No response
Relevant log output
No response
The text was updated successfully, but these errors were encountered: