Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.
This repository was archived by the owner on May 1, 2024. It is now read-only.

XAML compilation (XamlC) fails with generic types #1497

@Aquastorm

Description

@Aquastorm

Description

There's a bug in the Xamarin XAML compilation code that can be observed when referencing from XAML code a generic type having multiple type parameters and a concrete type is specified for one of them.
I think that the problem will be easier to understand with the example described below.

Steps to Reproduce

  1. Create a new cross-platform (Xamarin.Forms) project from VisualStudio. See the screenshot below to check which settings where used. You can also download the attached project.
    Note: the bug appears when compiling xaml code contained in either a .NET Standard Library or PCL project -> You can choose whatever platform you like (Android, iOS or UWP), it doesn't matter.

  2. Add the BaseValidationBehavior class to the root of the project.
    Note: the BaseValidationBehavior contains code (not shown here) common to all behaviors that validates user input:

using Xamarin.Forms;

namespace XamBugGenerics
{
    internal abstract class BaseValidationBehavior<TBindable, TModel> : Behavior<TBindable> where TBindable : BindableObject
    {
    }
}

Here both 'TBindable' and 'TModel' are type parameters.

  1. Add the EntryValidationBehavior class to the root of the project.
    This class contains code (not shown here) to validate 'Entry' views content.
using Xamarin.Forms;

namespace XamBugGenerics
{
    internal sealed class EntryValidationBehavior<TModel> : BaseValidationBehavior<Entry, TModel>
    {
    }
}

Note: 'TModel' is a type parameter but 'Entry' is a concrete type. Mixing type parameters and concrete types is what triggers the XAML compilation bug.

  1. Add the XAML compilation attribute shown below to the MainPage.xaml.cs:
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XamBugGenerics
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}
  1. Add an 'Entry' to the MainPage.xaml as shown below:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamBugGenerics"
             x:Class="XamBugGenerics.MainPage">

    <Entry VerticalOptions="Center" 
           HorizontalOptions="Center">
        <Entry.Behaviors>
            <local:EntryValidationBehavior x:TypeArguments="Entry"/>
        </Entry.Behaviors>
    </Entry>
</ContentPage>

Note: normally in a real project we should pass a model type as 'TypeArgument', but to reveal the bug any type can be used.

Expected Behavior

The XamlCTask is able to correctly compile the XAML code without raising an exception.
Actually the same code runs without issues when XAML compilation is deactivated.

Actual Behavior

By changing the logging verbosity of the XamlCTask in the Xamarin.Forms.targets file, you can observe this error in the build output window when building the project:

1>Target XamlC:
1>  Using "XamlCTask" task from assembly "C:\Users\[removed]\.nuget\packages\xamarin.forms\2.5.0.121934\build\netstandard1.0\Xamarin.Forms.Build.Tasks.dll".
1>  Task "XamlCTask"
1>    Compiling Xaml
1>    
1>    Assembly: obj\Debug\netstandard2.0\XamBugGenerics.dll
1>    ReferencePath: 	C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.0\build\netstandard2.0\ref\Microsoft.Win32.Primitives.dll;
1>		[multiple lines removed]
1>    DebugSymbols:"True"
1>    DebugType:"portable"
1>    Adding searchpath C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.0\build\netstandard2.0\ref
1>    Adding searchpath C:\Users\[removed]\.nuget\packages\xamarin.forms\2.5.0.121934\lib\netstandard1.0
1>		[multiple lines removed]
1>     Module: XamBugGenerics.dll
1>      Resource: XamBugGenerics.App.xaml... Has XamlCompilationAttribute set to Skip and not Compile... skipped
1>      Resource: XamBugGenerics.MainPage.xaml...
1>       Creating empty MainPage.__InitComponentRuntime ...done.
1>       Copying body of InitializeComponent to __InitComponentRuntime ...done.
1>       Parsing Xaml... done.
1>       Replacing MainPage.InitializeComponent ()... failed.
1>    D:\Dev\Xamarin\XamBugGenerics\XamBugGenerics\XamBugGenerics\MainPage.xaml : error : Object reference not set to an instance of an object.
1>       at Xamarin.Forms.Build.Tasks.TypeReferenceExtensions.ResolveGenericParameters(TypeReference self, TypeReference declaringTypeReference)
1>       at Xamarin.Forms.Build.Tasks.TypeReferenceExtensions.InheritsFromOrImplements(TypeReference typeRef, TypeReference baseClass)
1>       at Xamarin.Forms.Build.Tasks.SetNamescopesAndRegisterNamesVisitor.Visit(ElementNode node, INode parentNode)
1>       at Xamarin.Forms.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode)
1>       at Xamarin.Forms.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode)
1>       at Xamarin.Forms.Xaml.RootNode.Accept(IXamlNodeVisitor visitor, INode parentNode)
1>       at Xamarin.Forms.Build.Tasks.XamlCTask.TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, String resourceId, Exception& exception)
1>      Changing the module MVID...done.
1>
1>    Writing the assembly... done.
1>  Done executing task "XamlCTask" -- FAILED.
1>Done building target "XamlC" in project "XamBugGenerics.csproj" -- FAILED.

Because of this bug I had to deactivate XAML compilation on every page where I'm validating user input.

Basic Information

  • Version with issue: Xamarin.Forms 2.5.0.121934
  • IDE: Visual Studio Enterprise 2017 v15.5.2
  • Platform Target Frameworks: not relevant. The bug comes from either a .NET standard library or PCL project.
  • Nuget Packages: NETStandard.Library 2.0.0 and Xamarin.Forms v2.5.0.121934

Screenshots

Xamarin Forms project configuration
00 new cross platform app - xambuggenerics

Xamarin Forms project structure
01 project structure - xambuggenerics

Reproduction Link

XamBugGenericsCode.zip

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions