Skip to content

Commit a2f567b

Browse files
[XamlC] Avoid calling ResourceDictionary.SetAndLoadSource (#20776)
* Do not call ResourceDictionary.SetAndLoadSource from compiled XAML * Update public API * WIP * Fix importing references * Cleanup
1 parent 10dbf26 commit a2f567b

File tree

10 files changed

+77
-40
lines changed

10 files changed

+77
-40
lines changed

src/Controls/docs/Microsoft.Maui.Controls/ResourceDictionary.xml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -447,11 +447,11 @@
447447
<remarks>To be added.</remarks>
448448
</Docs>
449449
</Member>
450-
<Member MemberName="SetAndLoadSource">
451-
<MemberSignature Language="C#" Value="public void SetAndLoadSource (Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo);" />
452-
<MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetAndLoadSource(class System.Uri value, string resourcePath, class System.Reflection.Assembly assembly, class System.Xml.IXmlLineInfo lineInfo) cil managed" />
453-
<MemberSignature Language="DocId" Value="M:Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri,System.String,System.Reflection.Assembly,System.Xml.IXmlLineInfo)" />
454-
<MemberSignature Language="F#" Value="member this.SetAndLoadSource : Uri * string * System.Reflection.Assembly * System.Xml.IXmlLineInfo -&gt; unit" Usage="resourceDictionary.SetAndLoadSource (value, resourcePath, assembly, lineInfo)" />
450+
<Member MemberName="SetAndCreateSource&lt;T&gt;">
451+
<MemberSignature Language="C#" Value="public void SetAndCreateSource&lt;T&gt; (Uri value);" />
452+
<MemberSignature Language="ILAsm" Value=".method public hidebysig instance void SetAndCreateSource&lt;string&gt;(class System.Uri value) cil managed" />
453+
<MemberSignature Language="DocId" Value="M:Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource``1(System.Uri)" />
454+
<MemberSignature Language="F#" Value="member this.SetAndCreateSource : Uri -&gt; unit" Usage="resourceDictionary.SetAndCreateSource (value)" />
455455
<MemberType>Method</MemberType>
456456
<AssemblyInfo>
457457
<AssemblyName>Microsoft.Maui.Controls.Core</AssemblyName>
@@ -466,17 +466,20 @@
466466
<ReturnValue>
467467
<ReturnType>System.Void</ReturnType>
468468
</ReturnValue>
469+
<TypeParameters>
470+
<TypeParameter Name="T">
471+
<Constraints>
472+
<BaseTypeName>Microsoft.Maui.Controls.ResourceDictionary</BaseTypeName>
473+
<ParameterAttribute>DefaultConstructorConstraint</ParameterAttribute>
474+
</Constraints>
475+
</TypeParameter>
476+
</TypeParameters>
469477
<Parameters>
470478
<Parameter Name="value" Type="System.Uri" />
471-
<Parameter Name="resourcePath" Type="System.String" />
472-
<Parameter Name="assembly" Type="System.Reflection.Assembly" />
473-
<Parameter Name="lineInfo" Type="System.Xml.IXmlLineInfo" />
474479
</Parameters>
475480
<Docs>
481+
<typeparam name="T">To be added.</typeparam>
476482
<param name="value">To be added.</param>
477-
<param name="resourcePath">To be added.</param>
478-
<param name="assembly">To be added.</param>
479-
<param name="lineInfo">To be added.</param>
480483
<summary>For internal use by the Microsoft.Maui.Controls platform.</summary>
481484
<remarks>To be added.</remarks>
482485
</Docs>

src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,21 @@ public IEnumerable<Instruction> ConvertFromString(string value, ILContext contex
4545
var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath);
4646

4747
//fail early
48-
var resourceId = XamlCTask.GetResourceIdForPath(context.Cache, module, resourcePath);
49-
if (resourceId == null)
48+
var resourceTypeRef = GetTypeForPath(context.Cache, module, resourcePath);
49+
if (resourceTypeRef == null)
5050
throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value);
5151

52+
var resourceType = module.ImportReference(resourceTypeRef).Resolve();
53+
54+
// validate that the resourceType has a default ctor
55+
var hasDefaultCtor = resourceType.Methods.Any(md => md.IsConstructor && !md.HasParameters);
56+
if (!hasDefaultCtor)
57+
throw new BuildException(BuildExceptionCode.ConstructorDefaultMissing, node, null, resourceType);
58+
5259
var resourceDictionaryType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary");
5360

5461
//abuse the converter, produce some side effect, but leave the stack untouched
55-
//public void SetAndLoadSource(Uri value, string resourceID, Assembly assembly, System.Xml.IXmlLineInfo lineInfo)
62+
//public void SetAndCreateSource<TResourceType>(Uri value)
5663
foreach (var instruction in context.Variables[rdNode].LoadAs(context.Cache, currentModule.GetTypeDefinition(context.Cache, resourceDictionaryType), currentModule))
5764
yield return instruction;
5865
//reappend assembly= in all cases, see other RD converter
@@ -68,25 +75,17 @@ public IEnumerable<Instruction> ConvertFromString(string value, ILContext contex
6875
var uriVarDef = new VariableDefinition(currentModule.ImportReference(context.Cache, ("System", "System", "Uri")));
6976
body.Variables.Add(uriVarDef);
7077
yield return Create(Stloc, uriVarDef);
71-
yield return Create(Ldstr, resourcePath); //resourcePath
7278

73-
if (!string.IsNullOrEmpty(asmName))
74-
{
75-
yield return Create(Ldstr, asmName);
76-
yield return Create(Call, currentModule.ImportMethodReference(context.Cache, ("mscorlib", "System.Reflection", "Assembly"), methodName: "Load", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true));
77-
}
78-
else //we could use assembly.Load in the 'else' part too, but I don't want to change working code right now
79-
{
80-
yield return Create(Ldtoken, currentModule.ImportReference(((ILRootNode)rootNode).TypeReference));
81-
yield return Create(Call, currentModule.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true));
82-
yield return Create(Callvirt, currentModule.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true));
83-
}
84-
foreach (var instruction in node.PushXmlLineInfo(context))
85-
yield return instruction; //lineinfo
86-
yield return Create(Callvirt, currentModule.ImportMethodReference(context.Cache,
87-
resourceDictionaryType,
88-
methodName: "SetAndLoadSource",
89-
parameterTypes: new[] { ("System", "System", "Uri"), ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") }));
79+
var method = module.ImportMethodReference(
80+
context.Cache,
81+
resourceDictionaryType,
82+
methodName: "SetAndCreateSource",
83+
parameterTypes: new[] { ("System", "System", "Uri") });
84+
85+
var genericInstanceMethod = new GenericInstanceMethod(method);
86+
genericInstanceMethod.GenericArguments.Add(resourceType);
87+
88+
yield return Create(Callvirt, currentModule.ImportReference(genericInstanceMethod));
9089
//ldloc the stored uri as return value
9190
yield return Create(Ldloc, uriVarDef);
9291
}
@@ -103,5 +102,18 @@ internal static string GetPathForType(ILContext context, ModuleDefinition module
103102
}
104103
return null;
105104
}
105+
106+
private static TypeReference GetTypeForPath(XamlCache cache, ModuleDefinition module, string path)
107+
{
108+
foreach (var ca in module.GetCustomAttributes())
109+
{
110+
if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute"))))
111+
continue;
112+
if (ca.ConstructorArguments[1].Value as string != path)
113+
continue;
114+
return ca.ConstructorArguments[2].Value as TypeReference;
115+
}
116+
return null;
117+
}
106118
}
107119
}

src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,6 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
240240
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
241241
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
242242
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
243-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
243+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
244+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
245+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,6 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
255255
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
256256
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
257257
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
258-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
258+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
259+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
260+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,6 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
259259

260260
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
261261
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
262-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
262+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
263+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
264+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,6 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
215215
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
216216
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
217217
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
218-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
218+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
219+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
220+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,6 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
245245
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
246246
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
247247
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
248-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
248+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
249+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
250+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,6 @@ Microsoft.Maui.Controls.PlatformPointerEventArgs
209209
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
210210
Microsoft.Maui.Controls.Xaml.RequireServiceAttribute
211211
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.RequireServiceAttribute(System.Type[] serviceTypes) -> void
212-
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
212+
~Microsoft.Maui.Controls.Xaml.RequireServiceAttribute.ServiceTypes.get -> System.Type[]
213+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
214+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,5 @@ Microsoft.Maui.Controls.ContentPage.HideSoftInputOnTapped.set -> void
214214
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.get -> int
215215
*REMOVED*Microsoft.Maui.Controls.Entry.SelectionLength.set -> void
216216

217+
~Microsoft.Maui.Controls.ResourceDictionary.SetAndCreateSource<T>(System.Uri value) -> void
218+
*REMOVED*~Microsoft.Maui.Controls.ResourceDictionary.SetAndLoadSource(System.Uri value, string resourcePath, System.Reflection.Assembly assembly, System.Xml.IXmlLineInfo lineInfo) -> void

src/Controls/src/Core/ResourceDictionary.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,17 @@ public Uri Source
3939
}
4040

4141
//Used by the XamlC compiled converter
42-
/// <include file="../../docs/Microsoft.Maui.Controls/ResourceDictionary.xml" path="//Member[@MemberName='SetAndLoadSource']/Docs/*" />
42+
/// <include file="../../docs/Microsoft.Maui.Controls/ResourceDictionary.xml" path="//Member[@MemberName='SetAndCreateSource']/Docs/*" />
4343
[EditorBrowsable(EditorBrowsableState.Never)]
44-
public void SetAndLoadSource(Uri value, string resourcePath, Assembly assembly, global::System.Xml.IXmlLineInfo lineInfo)
44+
public void SetAndCreateSource<T>(Uri value)
45+
where T : ResourceDictionary, new()
46+
{
47+
_source = value;
48+
_mergedInstance = s_instances.GetValue(typeof(T), static _ => new T());
49+
OnValuesChanged(_mergedInstance.ToArray());
50+
}
51+
52+
internal void SetAndLoadSource(Uri value, string resourcePath, Assembly assembly, global::System.Xml.IXmlLineInfo lineInfo)
4553
{
4654
_source = value;
4755

0 commit comments

Comments
 (0)