diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 35feeaaa25..a455e2b3fc 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -24,11 +24,15 @@
+
+ $(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences
+
+
+ DependsOnTargets="$(BuildAvaloniaResourcesDependsOn)">
+ Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false"/>
@@ -64,7 +68,7 @@
/>
+ Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:CompileAvaloniaXaml /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false"/>
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index b364a06688..d1bfb25220 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -15,6 +15,7 @@ using XamlIl;
using XamlIl.Ast;
using XamlIl.Parsers;
using XamlIl.Transform;
+using FieldAttributes = Mono.Cecil.FieldAttributes;
using MethodAttributes = Mono.Cecil.MethodAttributes;
using TypeAttributes = Mono.Cecil.TypeAttributes;
@@ -125,6 +126,20 @@ namespace Avalonia.Build.Tasks
var parsed = XDocumentXamlIlParser.Parse(xaml);
var initialRoot = (XamlIlAstObjectNode)parsed.Root;
+
+
+ var precompileDirective = initialRoot.Children.OfType()
+ .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
+ if (precompileDirective != null)
+ {
+ var precompileText = (precompileDirective.Values[0] as XamlIlAstTextNode)?.Text.Trim()
+ .ToLowerInvariant();
+ if (precompileText == "false")
+ continue;
+ if (precompileText != "true")
+ throw new XamlIlParseException("Invalid value for x:Precompile", precompileDirective);
+ }
+
var classDirective = initialRoot.Children.OfType()
.FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
IXamlIlType classType = null;
@@ -136,6 +151,7 @@ namespace Avalonia.Build.Tasks
if (classType == null)
throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
initialRoot.Type = new XamlIlAstClrTypeReference(classDirective, classType, false);
+ initialRoot.Children.Remove(classDirective);
}
@@ -154,13 +170,43 @@ namespace Avalonia.Build.Tasks
var compiledPopulateMethod = typeSystem.GetTypeReference(builder).Resolve()
.Methods.First(m => m.Name == populateName);
+ var designLoaderFieldType = typeSystem
+ .GetType("System.Action`1")
+ .MakeGenericType(typeSystem.GetType("System.Object"));
+
+ var designLoaderFieldTypeReference = (GenericInstanceType)typeSystem.GetTypeReference(designLoaderFieldType);
+ designLoaderFieldTypeReference.GenericArguments[0] =
+ asm.MainModule.ImportReference(designLoaderFieldTypeReference.GenericArguments[0]);
+ designLoaderFieldTypeReference = (GenericInstanceType)
+ asm.MainModule.ImportReference(designLoaderFieldTypeReference);
+
+ var designLoaderLoad =
+ typeSystem.GetMethodReference(
+ designLoaderFieldType.Methods.First(m => m.Name == "Invoke"));
+ designLoaderLoad =
+ asm.MainModule.ImportReference(designLoaderLoad);
+ designLoaderLoad.DeclaringType = designLoaderFieldTypeReference;
+
+ var designLoaderField = new FieldDefinition("!XamlIlPopulateOverride",
+ FieldAttributes.Static | FieldAttributes.Private, designLoaderFieldTypeReference);
+ classTypeDefinition.Fields.Add(designLoaderField);
const string TrampolineName = "!XamlIlPopulateTrampoline";
var trampoline = new MethodDefinition(TrampolineName,
MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
classTypeDefinition.Methods.Add(trampoline);
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, rootServiceProviderField));
+
+ var regularStart = Instruction.Create(OpCodes.Ldsfld, rootServiceProviderField);
+
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
+
+ trampoline.Body.Instructions.Add(regularStart);
trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs
index deea89695d..167b75603f 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/AvaloniaXamlIlRuntimeCompiler.cs
@@ -137,8 +137,36 @@ namespace Avalonia.Markup.Xaml.XamlIl
static object LoadOrPopulate(Type created, object rootInstance)
{
var isp = Expression.Parameter(typeof(IServiceProvider));
+
+
+ var epar = Expression.Parameter(typeof(object));
+ var populate = created.GetMethod(AvaloniaXamlIlCompiler.PopulateName);
+ isp = Expression.Parameter(typeof(IServiceProvider));
+ var populateCb = Expression.Lambda>(
+ Expression.Call(populate, isp, Expression.Convert(epar, populate.GetParameters()[1].ParameterType)),
+ isp, epar).Compile();
+
if (rootInstance == null)
{
+ var targetType = populate.GetParameters()[1].ParameterType;
+ var overrideField = targetType.GetField("!XamlIlPopulateOverride",
+ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
+
+ if (overrideField != null)
+ {
+ overrideField.SetValue(null,
+ new Action