Skip to content
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

Markup Extensions :) :) :) #83

Closed
Mike-E-angelo opened this issue Mar 19, 2017 · 6 comments
Closed

Markup Extensions :) :) :) #83

Mike-E-angelo opened this issue Mar 19, 2017 · 6 comments
Assignees
Labels
enhancement (cc: feat) New feature or request
Milestone

Comments

@Mike-E-angelo
Copy link
Member

I have been thinking lately that I would be remiss to spend so much time and energy on this project and not enable markup extensions, my favorite feature from Xaml. This would in effect make EXS as a Xaml parser in addition to being a XML POCO parser.

This should be an extension, obviously. FWIW while I am not the happiest with the ConfigurationAPI (I'd rate it like 6/10), I am very happy with the ExtensionModelAPI (an 8 or 9 out of 10). Lots of cool stuff there and I think it's a great new way to look at serialization. 👍

@Mike-E-angelo Mike-E-angelo added enhancement (cc: feat) New feature or request v2 labels Mar 19, 2017
@Mike-E-angelo Mike-E-angelo self-assigned this Mar 19, 2017
@WojciechNagorski
Copy link
Member

I like your changes in Configuration, but I don't know what you want to do in this issue .

@Mike-E-angelo
Copy link
Member Author

Mike-E-angelo commented Mar 20, 2017

So Markup Extensions are an awesome feature of Xaml that allow you to provide runtime values for a property while the object is being serialized. They also allow you to tie into the object that is being serialized so that you can do cool things with it as time goes on (like binding).

Super simple example here:

public class MyMarkupExtension : IMarkupExtension
{
	public object ProvideValue(IServices services) => "Hello World"; // <-- could be from a web service or anywhere.
}
class Instance
{
	public string PropertyValue { get; }
}

<Instance PropertyValue="{x:MyMarkup}" />
var serializer = new ExtendedConfiguration().Create();
var actual = serializer.Deserialize<Instance>();
Assert.Equal( actual.PropertyValue, "Hello World!");

Another scenario could be how we use references. Instead of using custom attributes (exs:reference/identity), we could use markup extensions instead. That's how Xaml does it. :)

@Mike-E-angelo Mike-E-angelo added this to the v2.1 milestone Mar 24, 2017
@Mike-E-angelo Mike-E-angelo removed the v2 label Mar 24, 2017
@Mike-E-angelo Mike-E-angelo modified the milestones: v2, v2.1 Mar 25, 2017
@Mike-E-angelo
Copy link
Member Author

Mike-E-angelo commented Apr 1, 2017

OK this took a little longer than expected, but we now have a very simple implementation of markup extensions with core support for default framework markup extensions such as Null, Type, and Static. Basically got done in one week what the entire UWP group has taken nearly seven years to do. ;)

Example of the static extension (and others) can be seen here.

Please note that in addition to specifying strings for values within a markup extension, I took it one step further so that you can use actual .NET/C# expressions within it. So let's say you have an extension like this:

sealed class NumberExtension : IMarkupExtension
{
	readonly int _number;

	public NumberExtension(int number)
	{
		_number = number;
	}

	public object ProvideValue(IServiceProvider serviceProvider) => _number;
}

sealed class Subject
{
	public int Number { get; set; }
}

You are able to use it in your markup as such:

<?xml version="1.0" encoding="utf-8"?>
<Subject xmlns="clr-namespace:YourNamespace;assembly=YourAssembly" PropertyName="{Number 3 * 4}" />
var subject = new ExtendedConfiguration().EnableMarkupExtensions()
			                 .Create()
			                 .Deserialize<Subject>(xml);
subject.Number.Should().Be(12);

Cool huh! Unfortunately (or fortunately, depending on your perspective :) ), in order to do this, we had to take on a dependency. Currently, it is using the very powerful and handy Eval-Expression.NET. It is free for the first 50 characters. I am in communication with @JonathanMagnan in regards to this to see if we can somehow get a pro version if we give it special mention/thanks in our README. Jonathan has said that they should have something together by Monday to discuss.

Also a consideration here Jonathan (and feel free to reply here): currently we are using all of our dependencies inline. So we currently have two dependencies in Sprache and LightInject. Both of them have been placed in our Core folder with licenses provided for both.

Will this be OK for your project as well?

I will be closing this issue to mark as done for now to get it off our list towards the milestone. Please feel free to continue to comment.

@WojciechNagorski
Copy link
Member

Mike-E-angelo added a commit that referenced this issue Apr 3, 2017
@Mike-E-angelo
Copy link
Member Author

Hah! It sure did. Is there a notification for this, perhaps? Seems like an important one to know. :)

The break is actually due to Eval-Expression.NET. It looks for a new package at the start of every month. I believe this is what Jonathan and team are looking for in our case here.

I just committed a fix. HERE GOES NOTHING!! 😆

@Mike-E-angelo
Copy link
Member Author

OK this looks like this is working as expected now. Let me know if it is otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement (cc: feat) New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants