cwensley / Portable.Xaml

Portable .NET library for reading/writing xaml files.
Other
158 stars 39 forks source link

x:Class / Compiled Xaml Support? #23

Open Mike-E-angelo opened 8 years ago

Mike-E-angelo commented 8 years ago

This project is starting to look like the true successor of System.Xaml, and I am enjoying all the activity that I am seeing here. :smile:

One thing that I wanted to get on the radar here is x:Class/compiled Xaml support. Is this possible with Portable.Xaml? That is, I would like to be able to define a Xaml file in my project, and this file has an x:Class attribute that essentially takes the Xaml and compiles it into an embedded resource somehow into the assembly. FWIW, this is one of the cool aspects of Xamarin's Xaml system in that it does this (along with WPF's of course).

If this is not on the radar/implemented, I might be interested in helping out defining this. Granted if I get some free time, of course! Haha.

cwensley commented 8 years ago

Hi @Mike-EEE, thanks for submitting the issue!

I've been thinking of making a code writer (that would be extensible for various languages, c# being the first obviously). What I would like this to do is generate compilable code that won't require parsing Xaml at runtime. I've made great strides making Portable.Xaml more efficient than it was, but eliminating it completely would certainly be ideal.

The idea is then you could make msbuild targets that would use this feature, and compile .xaml files when you build your project. If done properly, it would also allow autocompleting x:Name identifiers while writing code.

Mike-E-angelo commented 8 years ago

Correct... essentially maybe using Roslyn to create the compilation instructions? I've thought about this, too. :) BAML is what I was thinking of, btw. :sunglasses:

cwensley commented 8 years ago

Yeah, I figured that was the idea (BAML). I think we could accomplish the same sort of thing using pure code generation though instead of creating a binary reader/writer. However I'm open to whatever approach makes sense (;

Mike-E-angelo commented 8 years ago

Haha cool... I've been wanting to get familiar w/ Roslyn. :smile:

grokys commented 8 years ago

Yeah, code generation sounds like a great feature! Much more useful than BAML or something similar.

cwensley commented 7 years ago

Ok so I've written a very basic XamlWriter that writes some code using Roslyn and came across a glaring problem that I haven't quite figured out yet.

Basically, to parse the xaml the project needs to be compiled if you use any local types. However, you can't compile unless the stub for the named objects is generated if you use them from the partial class.

Perhaps it needs to fake the types when reading the xaml and just assume everything is available? But then you have the problem of how to read the xmlnsdefiniton attributes.

Classic chicken and egg problem here. If we could just figure this out we can get the xaml compiled directly to code fairly soon.

I think I'm starting to figure out why MS decided to use a BAML for this...

Mike-E-angelo commented 7 years ago

Ahhh I wish I had some cycles to put into this. I am really glad (and impressed!) that you are checking this out. I do know that Xamarin.Forms does something close to this, using EmbeddedResource... might be worth a looksee to how they do it?

Maybe it also doesn't work with local classes to the project it is contained. FWIW, I am fully OK with this being a limitation for a v1.0 feature. When using Xaml I have it in a dedicated project anyways that references all the required assemblies that contain the items I am describing.

grokys commented 7 years ago

It's been a while since I've worked with Roslyn, but I imagine there must be a way to add a type that hasn't yet been declared? It wouldn't need to compile immediately but instead create a .cs file and when that file is included in the project and compiled all the types would resolve.

Mike-E-angelo commented 7 years ago

Ahhhh good point @grokys. I was thinking of that, too. Roslyn does compile C#/VB projects, after all. There must be a sorting/priority mechanism that is in place to properly resolve the symbols.

cwensley commented 7 years ago

It's not Roslyn that's the problem, as you can just specify types and identifiers by strings. It's loading the xaml, which if it used the same Xaml parser, could not load unless the types are pre-compiled.

From what I understand on how Xamarin.Forms does this, is it creates a stub .cs file that just calls XamlServices.Load() to load the embedded resource, and it also picks out any identifiers and generates the partial class and members.

I couldn't imagine a way this can be done with the standard Xaml parser, so it'd have to just load the xml using the standard xml parser and look for x:Name, though it wouldn't know if any of your classes map a different property using the RuntimeNamePropertyAttribute.

It'd be interesting if we can somehow work into the roslyn compile process where it's loaded all of the metadata of the existing code, but not generated the .dll yet. We could then get all the type and member information from roslyn, generate the code, and then get it compiled in the same .dll.

Mike-E-angelo commented 7 years ago

Another consideration might be to look into PostSharp. It has some pretty awesome magic when it comes to compiling assemblies. Here's an aspect that deals with assembly resources, for instance: http://doc.postsharp.net/resource-introduction

They provide (free) open source licenses for projects as well. Not sure if it would be useful for this scenario, but I wanted to make sure you are aware of it.