Pages

Sunday, 22 May 2016

Karabow: Hardware, Software, Services


Disclaimer: The opinions expressed here are my personal opinions, and do not necessarily represent those of Karabow.

We have been hard at work for over a year now and, while we are still trying to put finishing touches to some of the projects we have been working on, I believe it's not too early to start sharing some of our activities and progress with the wider public. We are Karabow , and Karabow is hardware, software, services.

Hardware


Hardware is the starting point of our dream, and the end of most of our efforts. We are very passionate about the devices we are building (and will be building), and we can't wait to share them with the wider public. We will start from the basic devices and work our way up to the flagship devices.

Importing Knowledge

Currently the bulk of our hardware endeavours is done outside the borders of Nigeria. One of our major long-term goals is to import all major pieces of knowledge for hardware design and manufacture to the country. This is a journey of a thousand miles, and we are willing to tread this path one step at a time. We know the future we desire, and we know it's in our hands to bring it to pass.

Software


While hardware may be our primary focus, software provides a strong opportunity to differentiate our devices from the pack. That is, while we try to build our devices as compelling as possible, we also put great efforts into the pieces of software that come with them. Our software efforts range from application software (apps) to system software (like custom kernels and ROMs), but they all serve to add values to our devices and to the lives of those using our products.

Open Source Player

Karabow is also going to be a very active player in the open source space. Currently we have projects like Melon OS and Pluginizer being developed on GitHub (https://github.com/karabow-inc/). Some projects are being developed off GitHub or in private repositories, and we will be opening up such repositories soon, as well as adding more open source projects to GitHub. There is a deep respect for "side-projects" at Karabow, and a good number of these side-projects will also be making it out as open source projects.

Services


We recognise that the skill set we possess in-house will be of great benefit to a lot of organizations that may not be in a position (or may not be willing for various reasons) to possess such. That is why we intend to set up KaraHub (http://www.karahub.com/). KaraHub will render services ranging from graphics content development to app development. KaraHub will also seek to connect developers (including graphics developers) with job opportunities, and (in the distant future) provide affordable conducive workspaces for developers.

#NotWithABang


We don't necessarily intend to start with a bang. We are a young company, and we want to grow organically. This #NotWithABang mentality will be reflected in many of our early products and decisions, including how we present ourselves online.

For our hardware enterprise, this implies we will be starting with a limited number of feature phones and simple devices, and grow from there until we get to release our flagship phones. One of such simple devices is the Fundy (http://www.karabow.com/Fundy_Tab) tablet for kids. This is not the most original item that will come out of Karabow, but it is a necessary step. This product has already helped us establish good relationships with schools and other institutions, relationships we will be exploiting when our fancier items are ready for the market. Fundy is also important financially, in that it is our first source of steady income. In February 2016 (the first month of sales) we made a modest 90,000 in sales. By the end of the first quarter of the year we had made 235,000 in sales. As for this second quarter we have already sold tablets worth over 800,000, with more orders on the line. These numbers may be small in the grand scheme of things, but we are exactly where we planned to be at this point in time.

For software, #NotWithABang implies we will be releasing our consumer products, but in humble steps, building up a modest clientèle even before we are ready to publicly announce such products. We will also be releasing some developer tools we built to help us develop those products. This is exactly the step we have taken with our Unify (http://unifyedu.com/) school information management system. Unify is still under development but we already have a few schools testing it out, and more lined up. Unlike Fundy, we don't expect much from Unify in the next six months as schools try it out for free. But, beyond that, its returns are tremendous. Unify, however, is not just about the finances; it's more about the data it gets to collect from the schools and institutions using it. When I think about the analytic engines and artificial intelligence we can build around such data I get excited for the future of Karabow.

It's All About the Journey


We have a clear vision of where we are going to. But we also realize that the journey will be a long one. There are more projects in the pipeline, projects that are exceedingly more interesting than the ones described above. I can hardly wait. But I also recognise that this journey must be taken one step at a time. So while we keep our destination in mind, we have decided to enjoy the journey. This is going to be one awesome adventure, and we hope you ride along with us.


Do not forget to like our page on facebook (https://facebook.com/karabowng) , and follow us on twitter (https://twitter.com/karabowng).

Yours truly,
Chieze Franklin,
Software developer, Karabow.

Sunday, 8 May 2016

Thank You (2016 Edition)

On this beautiful day, and as a proud Christian, let me begin by thanking God for keeping me to see yet another year of my life. He remains faithful, even in my unfaithfulness.



I will also like to thank all well-wishers. May we all always have causes to celebrate.

Let me use this year's edition of my birthday celebration to thank some very special people who have helped shape my life as a software developer to this point. The words herein are in no way sufficient to express how much you have done for me, and how much you mean to me. Please accept my gratitude.

I would like to thank Aremu Oluwaseun Francis. You, more than any other person, opened the door to the world of software development for me. My very first steps as a developer were taken under your tutelage. VB.NET, C#, Windows programming, ASP.NET, Web API; the list of the stuff you taught me goes on an on. Because of you I am married to Windows *smile*.

Next, let me thank Chidiebere Ikenna Nnadi. To you, you did nothing more than just give me materials on Android development. But those materials created a new hunger in me. For the first time I could see a world way bigger than Windows and Microsoft. I may be married to Windows but because of you I started a very fierce affair with Android *wink*.

Last (but by no means the least) on my Thank You list today is Aliyu Muhammed (Andromadus MobileXP). From my very first days as a programmer I have been fascinated by the concept of an operating system. I would often daydream about being part of a crazy group of programmers who are working on this crazy operating system. I have often tried to find books and materials for operating system development, but something was always missing - a human guide. In Andromadus I have found that guide. I now have access to tools for building operating systems, as well as access to others who have gone before me in this field. To be honest I haven't been a very dilligent student in the space but I'll catch up. Operating system programming is something I thought I would be doing by 28 or 29 but now I am ahead of my time-table. With this new knowledge I feel almost complete as a software developer.

The future also looks promising. With a friend like Samuel Adeshina, who is consistently the top rated Nigerian PHP developer on PHP Classes (http://www.phpclasses.org/) I will definitely get my hands dirty in the field of artificial intelligence, and with Abdul Saidu I have already taken my first steps in game development.

Obviously, the list of those who have influenced me as a software developer goes way beyond this. And I am grateful to every one of them.

Before I conclude this post, let me just chip this in. Most of the software solutions I find myself working on these days are development tools: tools for fellow software developers. So a few weeks ago I decided to make it a hobby releasing fun apps for "regular" people every year, on my birthday. I had wanted to release a web API for interacting with a chess-playing bot, but found the time at hand really limited. I then decided to make an age-telling twitter bot. You would tweet a picture of your face to it, and it would guess your age (amongst other things) and tweet that back to you. Yes, you guessed right, it uses Microsoft Project Oxford (https://www.microsoft.com/cognitive-services/) behind the scene. I, however, couldn't overcome my laziness to see the project through. With no pet project to talk about this year, let me use this opportunity to just mention a project we at Karabow have been working on for some time now - Unify (unifyedu.com). The project is in it's VERY EARLY stages, although we already have certain institutions trying it out. I'll write more on Unify at a later date to discuss some of the pieces of technology we had to develop in-house in order to build Unify.

Friends matter. If you can find people to point you to the right direction, happy you!

P.S: Today is a very special day indeed, even the Cosmos agrees. Today the transit of planet Mecury across the face of the sun can be witnessed from Earth, an event that occurs as rare as 13 times in a century (http://www.slate.com/blogs/bad_astronomy/2016/05/05/guide_to_the_mercury_transit_on_may_9_2016.html).


Monday, 25 April 2016

Introducing the Quic Web Development Framework - Part 2

GitHub repo: https://github.com/Chieze-Franklin/Quic

Introduction

Quic is a web development framework that enables you create rich web applications with less code than is usually needed.
Quic is basically a preprocessor; it goes through your HTML file, looking for custom tags, and producing standard HTML, CSS, JavaScript (and pretty much anything) from such tags.
When a custom tag is encountered Quic loads the appropriate assembly and locates a class with the same name as the tag. The class is then instantiated, and its Render method is called to emit the relevant codes and/or files.
So we can say Quic allows you to delegate the dirty jobs to a class, and include that class in your HTML file as a custom tag.

Background

In the first part of this article, Introducing the Quic Web Development Framework - Part 1 (http://www.codeproject.com/Articles/1077305/Introducing-the-Quic-Web-Development-Framework-Par) we were introduced to the Quic framework, its uses, the ideas behind it, and its advantages.
Some of the advantages we mentioned are:
  • There are no tags.
    Quic has no custom tags of its own. So, technically, you don't have a lot of new things to learn.
  • Works well with any XML document.
  • Quic makes your code more readable.
  • Easy to refactor.
  • Quic does more than just emit code.
    Quic doesn't just emit codes, it can create needed files in the output directory.
  • Works well with other web frameworks.
    Quic works well with other web frameworks/technologies because Quic is simply a preprocessor. It goes through your file looking for custom tags that make sense to it. Every other content on the file is left untouched.
We ended the article with a healthy discussion of the Quic-specific attributes expected in a <html> tag.
In this article, we'll begin by refreshing our memories of the Quic bar. We will take a look at what Quic expects to find in the <head> and <body> tags. We will then learn about value providers. Finally, I will list all the custom tags (and their respective attributes) defined in the assemblies packaged with this article so that you can start utilizing them in your web pages.
To successfully follow the source codes in this framework, all you need is a healthy knowledge of C#. Two of the core namespaces used are System.Xml.Linq (I previously used System.Xml, but found it difficult retrieving line number and column number information) and System.Reflection to help me load the relevant assemblies and classes.

Getting Started

System Requirements

  • The app was originally built on a Windows 8 machine, but should run with no modification on Windows 7 and Windows 10.
  • The target framework is .NET Framework 4.5, but the source code can be built against many previous versions, as well as future versions.

The Quic Bar

You can skip this part if you have read it in the previous article.
I am assuming you have downloaded (and extracted files from) the relevant zip files.
  • Run the solution; the start-up project should be Quic.App, so this should run the Quic.App.exe executable.
  • The Quic bar is an always-visible floating toolbar. It's size allows you to continue writing your markup in your preferred editor, returning easily to the bar whenever you are ready to build the file. When maximized, the bar is fixed at the top of your screen, but when in normal window mode (restored), it can be dragged to any location on the screen.
    In building a file, custom recognizable tags in the file are interpreted/processed, similar to how a PHP interpreter/engine works on a PHP file. Unlike a PHP engine which may send the result of the processing to a browser, the Quic bar saves its own result as an output file in the specified output directory, along with every other asset that was generated during the build.
  • Using the Quic bar is easy. Having typed your markup in an editor of your choice, select the file (file extension is irrelevant), select your output directory, then click the Build source file button.
  • The Show/hide notifications button will have a green badge on it if the build was successful. Click the button to view any available notifications.
  • Click the Open output directory button to navigate to the output directory.
    Notice the auto-generated files and folders in the output directory.

Using Quic Custom Tags on Your Web Pages

Basic Structure

Because of the focus on HTML documents, Quic expects the root tag of the document to be <html>. Quic expects your <html> tag to have <head> and <body> tags. These tags are always in lower case.
In the first part of this write up we looked at the <html> tag, and the Quic-specific attributes expected in it. These attributes were classified into namespace attributes,processing option attributes, and the output file attribute.
Here we discuss the <head> and <body> tags. A sample Quic document is shown below.

The <head> Tag

With respect to Quic, the <head> tag is expected to contain resource elements. These elements usually do not contribute to the UI of the web page directly, instead serving as helpers for UI elements.
Resource elements inherit from the class Quic.ResourceElement [Quic\Core\Elements\ResourceElement.cs]. Quic.ResourceElement inherits from the classQuic.Element [Quic\Core\Elements\Element.cs], and adds a string member property called Key. This property can be set from mark-up.
In every Quic document, resource elements with their Key attributes set to a valid identifier are stored in a resource dictionary (this implies two resource elements cannot have the same key), and can be referenced many times in the document using their keys. We will see how to reference resource elements when we discuss value providers.
Resource elements with no Key attributes set are invoked (usually by calling their Render methods) only once, when the output file is being generated, and discarded afterwards.
In the sample document shown above, looking at lines 16-18, you can see 3 resource elements: <UseBootstrap><ColorProvider> and <StringProvider>. Notice that the first has no Key attribute set. That is because we need that particular resource element only once in the document (to create the necessary bootstrap files).

The <body> Tag

With respect to Quic, the <body> tag contains UI elements. These elements define the user interface of the document.
UI elements inherit from the class Quic.UIElement [Quic\Core\Elements\UIElement.cs]. Quic.UIElement inherits from the class Quic.Element[Quic\Core\Elements\Element.cs], and adds many UI-centric properties that can be set from mark-up, like BackColorTextWidth.
All elements (UI and resource elements) come with a Name property that can be set from mark-up. In every Quic document, elements with their Name attributes set to a valid identifier are stored in an element dictionary (this implies two elements cannot have the same name). This is of particular importance to UI elements because giving a UI element a name allows the attributes of that element to be accessed in other parts of the document. For instance, on line 106, we set the text property of the button element named btn2 to the value of the text property of the element named btn1.
<Button Name="btn2" Text="{$btn1.Text}" />
This notation will be explained further under value providers but the syntax is simple to grasp. To access the value of an element's attribute, start with an opening brace {followed by a dollar sign $ then the element's name then period . then the attribute name then a closing brace }.

Value Providers

When assigning a value to an attribute, the value can either be a literal value or an expression value.
A literal value simply starts with a quotation mark and ends with a matching quotation mark, and always represents a string object. In the example shown below, the Textattribute of the <Button> tag is set to the literal string object, "My First Button"
<Button Name="btn1" Text="My First Button" />
An expression value starts with a quotation mark followed by a single opening brace, and ends with a closing brace followed by a matching quotation mark, and can represent any type of object. In the example below, the Text attribute of the <Button> tag is set to an expression value: the actual value will be computed when the page is being parsed.
<Button Name="btn2" Text="{$btn1.Text}" />
The object that computes/evaluates an expression value is called a value provider. A value provider must implement the interface Quic.IValueProvider[Quic\ValueProviders\IValueProvider.cs], and this involves implementing the overloaded Evaluate methods which convert the input argument of the value provider to an appropriate output.
Within the matching braces of an expression value there are two ways to invoke a value provider:
  1. By class name
  2. By using a key in the document's resource dictionary
To demonstrate the various ways of calling a value provider, I will use the value provider StringProvider [Quic.Core\ValueProviders\StringProvider.cs]. This is basically an alias for Quic.StringVP [Quic\ValueProviders\StringVP.cs] which (for now) does nothing other than return the input argument passed into it as output, as shown in itsEvaluate methods:
public override object Evaluate(object input)
{
  return Evaluate(input.ToString());
}

public override object Evaluate(string input)
{
  return input;
}

Invoking Value Providers By Class Name

After the opening brace of the expression value, type the name of the class from which the value provider object would be instantiated. If the value provider expects an argument/input (most value providers do), then type the argument after the class name, separating them with a space. For instance, on line 114, we have:
<Button Name="btn4" Text="{StringProvider My Fourth Button}" />
In the code snippet above, the value provider that will provide the value for the Text attribute of the <Button> tag is a StringProvider, and its agument is My Fourth Button.
To instantiate this value provider, Quic must first find a matching namespace attribute, and it finds it on line 5:xmlns:StringProvider="Quic.Core.dll:StringProvider".
This means in the assembly Quic.Core.dll there is a class named StringProvider from which Quic will instance an actual object (which must be a value provider, or an exception is thrown), and invoke the Evaluate method of the object, with "My Fourth Button" as the method's argument.
On line 117 we have something similar:
<Button Name="btn5" Text="{String My Fifth Button}" />
In the code snippet above, the value provider that will provide the value for the Text attribute of the <Button> tag is a String, and its agument is My Fifth Button.
Quic must first find a matching namespace attribute, and it finds it on line 8: xmlns:String="Quic.Core.dll:String".
To instantiate this value provider, Quic searches for the appropriate class as earlier described. The problem is, there is no class named String in Quic.Core.dll.
When Quic doesn't find a class with a matching name in the specified assembly, it suffixes the string "Provider" to the class name and performs the search again. Only if this second search fails does it throw an exception.
In this case, it suffixes "Provider" to "String" to form "StringProvider", and, this time, it finds the desired class.

Invoking Value Providers By Using a Key in the Document's Resource Dictionary

Because most value providers that convert string to basic types like Boolean, Color, DateTime are expected to be resources (extending Quic.ValueProviderResource[Quic\ValueProviders\ValueProvider.cs] which in turn extends Quic.ResourceElement), they have a Key attribute and can be specified in the <head> tag, as seen on line 18.
<StringProvider Key="sp" />
To invoke a value provider by its key, after the opening brace of the expression value, type the at character @ followed immediately by key. If the value provider expects an argument/input (most value providers do), then type the argument after the key, separating them with a space. For instance, on line 120, we have:
<Button Name="{@sp btn6}" Text="{@sp {String My Sixth Button}}" />
In the code snippet above, the value provider that will provide the value for the Name attribute of the <Button> tag is one with the key sp which, from line 18, is aStringProvider, and its agument is btn6.
The advantage of this method (over using the class name) is that the value provider is created only once and reused wherever its key is specified.

Nested Value Providers

The argument of a value provider can be another value provider. This is allowed since every value provider is expected to accept an argument and return a result. The inner value provider executes first, and its result becomes the argument for the outer value provider.
An example is seen on line 120:
<Button Name="{@sp btn6}" Text="{@sp {String My Sixth Button}}" />
The Text attribute of the <Button> tag will get its value from a value provider that has been stored in the document's resource dictionary with the key sp, which in turn will get its argument from an instance of StringProvider (which will be created at that point) with argument My Sixth Button.
The level of nesting can go on indefinitely. When working with nested value providers, be sure to make every opening brace have a corresponding closing brace.

Property Provider

There is a useful value provider that comes with Quic, in the Quic.Core.dll assembly, called PropertyProvider [Quic.Core\ValueProviders\PropertyProvider.cs]. This value provider helps to reference the property/attribute values of elements.
Suppose I wanted to create three buttons, all having the same text, without having to repeat that text verbatim, I could simply set the text in the first button, and then reference it in the second and third buttons using PropertyProvider value provider, as shown below:
<Button Name="btn1" Text="My First Button" />
<Button Name="btn2" Text="{core:PropertyProvider btn1.Text}" />
<Button Text="{core:PropertyProvider btn1.Text}" />
Now all three buttons will have the same Text attribute. Additionally, if I need to change their Text attributes, I need only do it on btn1.

Default Property Provider {$}

Because of how useful the PropertyProvider is, every Quic document comes with a default PropertyProvider. What's more, there is a very convenient way of accessing it: type the dollar sign $ after the opening brace, followed by the argument to the PropertyProvider. There's usually no need to leave any space between the$ and the argument. The above example can thus be rewritten as (as seen on lines 105 and 108):
<Button Name="btn1" Text="My First Button" />
<Button Name="btn2" Text="{$btn1.Text}" />
<Button Text="{$btn1.Text}" />
PropertyProvider expects the following formats of argument:
  • {element-name}.{attribute}: This returns the value of the attribute {attribute} of the element with name {element-name}.
    See line 106:
    <Button Name="btn2" Text="{$btn1.Text}" />
    
  • {attribute}: This returns the value of the attribute {attribute} of the current element.
    See lines 82 and 83:
    <Table Text="Awesome Table" Bordered="true"
     Condensed="{$Bordered}"
    
  • this.{attribute}: This returns the value of the attribute {attribute} of the current element (same as above).
    See lines 82 and 84:
    <Table Text="Awesome Table" Bordered="true"
     Hover="{$this.Bordered}"
    
  • self.{attribute}: This returns the value of the attribute {attribute} of the current element (same as above).
    See lines 82 and 85:
    <Table Text="Awesome Table" Bordered="true"
     Striped="{$self.Bordered}"
    
  • parent.{attribute}: This returns the value of the attribute {attribute} of the parent element of the current element.
    See line 124:
    <TD Context="{?$parent.Context}">
    
    NOTE: The question mark, ?, after the opening brace represents lazy evaluation.

Lazy Evaluation {?}

As expected, a Quic document is processed top-to-bottom. Whenever Quic comes across a referenced attribute, it expects that attribute (and the tag that it belongs to) to have been defined before that point. This is why we defined btn1 before accessing btn1.Text, or why we typed Bordered="true" before typing Condensed={$Bordered}. If an attribute is referenced before it is defined an exception may be thrown. (In the case of Condensed={$Bordered}, an exception will not be thrown but the default value of Bordered, which is false, will be used.) To avoid such outcomes we use the lazy evaluation syntax.
Lazy evaluation uses the same syntax as regular expression values, except that a question mark, ?, must immediately follow the opening brace, as seen on line 137:
<Button Text="{?$btn8.Text}" ButtonType="success" ng-model="angularJsModel" />
The Text attribute of the above <Button> references the Text attribute of an element named btn8 (which is not created until line 140). However, because of the ?following the opening brace, this attribute will be evaluated lazily. This means the attribute will NOT be evaluated when the input XML file is being parsed to create the Quic document object, but will be evaluated when the Quic document object is being rendered to the output HTML file and, by then, the element named btn8 must have been created.
Lazy evaluation MUST be used when accessing parent attributes, as seen on line 124:
<TD Context="{?$parent.Context}">
This is because a parent element is fully created only after it's child elements have all been created.
Lazy evaluation can be used with any value provider, not just PropertyProvider. So you could have:
<Button Name="btn4" Text="{?StringProvider My Fourth Button}" />
NOTE: Lazy evaluations may incur a slight performance overhead.

Escaping the "{" Character

If the value of an attribute is expected to be a literal value which starts with the { character, in order for it not to be taken as an expression value by Quic, you have toescape the { character by typing {{.
<Button Text="{{$this.Text}" />
The Text attribute above will be assigned the string "{$this.Text}".
Note that if the attribute value starts with a { but does not end with a }, it is also taken as a literal value. In this case, you should not escape the { character because Quic will take the value as a literal value. In other words, for Quic to take a value as an expression value, it MUST begin with a single { character and end with a matching }.

Value Providers in Tags

The content of a tag can also be provided by a value provider, as seen on lines 25 and 26:
<MI Link="">{@sp Second SubMenu Item}</MI>
<MI Link="">{StringProvider Third SubMenu Item}</MI>
Similar rules apply here as do when using value providers with attributes.

Implicit Value Providers

You can register a value provider as an implicit value provider. Implicit value providers don't have to be explicitly specified; Quic will invoke the appropriate implicit value provider based on the element/tag being acted on, and the attribute that is being assigned.
To explain the importance of registering implicit value providers, I'll use the class ColorProvider [Quic.Core\ValueProviders\ColorProvider.cs]. As you may have guessed, this value provider helps convert a string literal to a System.Drawing.Color object. To use it explicitly, I could type:
<winform:Button BackColor="{ColorProvider red}" />
If, however, I register ColorProvider as an implicit value provider in the matching class for <winform:Button>, then I could rewrite the above line simply as:
<winform:Button BackColor="red" />
This is the advantage of implicit value providers: you do not have to specify the value provider to use explicitly.
To register implicit value providers for a Quic element, override the GetImplicitValueProvider method.
Every Quic element comes with a number of implicit value providers because they are registered in the GetImplicitValueProvider method of the most fundamental class, Quic.Element.

This is why every Quic element knows how to convert string literals provided as attribute values to the appropriate objects of basic data-types. For instance, theQuic.PointVP [Quic\ValueProviders\PointVP.cs] value provider converts a string input into a System.Drawing.Point object.

Check out the interesting source code for Quic.ColorVP [Quic\ValueProviders\ColorVP.cs].
The implicit value providers registered for Quic.Element are not often sufficient. This is why you have the liberty to override the GetImplicitValueProvider method. This is exactly what we do in a number of Quic.Bootstrap.dll elements. For instance, the very core class BootstrapElement [Quic.Bootstrap\Elements\BootstrapElement.cs] provides its own implementation of the GetImplicitValueProvider method:
public override IValueProvider GetImplicitValueProvider(string propertyName, Type propertyType)
{
  if (propertyName == "Align")
  {
    return AlignmentProvider.Singleton();
  }
  else if (propertyName == "State")
  {
    return StateProvider.Singleton();
  }
  else if (propertyName == "Validation")
  {
    return ValidationStateProvider.Singleton();
  }

  return base.GetImplicitValueProvider(propertyName, propertyType);
}
Check out the source codes for the implicit value providers registered in various Quic.Bootstrap.dll elements in Quic.Bootstrap\ValueProviders\.

Value Providers Limitations

The current implementation of value providers has some serious limitations.
  1. A value provider accepts only one argument. Everything after the value provider is a single argument, including spaces. I would love to change that one way or another. The current implementation has the format: Attribute="{ValueProvider arg}". I would love to implement the format: Attribute="{ValueProvider arg1, arg2, arg3, ...}"
  2. A value provider must be the only content of a tag or attribute value. I would love to change that so that multiple value providers (not nested, but siblings) can occur in a tag or attribute value, or so that a value provider can be interpolated within the content of a tag or attribute value. The current implementation has the format:<Tag>{ValueProvider arg}</Tag>. I would love to implement the format: <Tag>...{ValueProvider1 arg}...{ValueProvider2 arg}...{ValueProvider3 arg}...</Tag>

A Proposal for a Manifest File

Let me end this article with a proposal. I propose that custom element creators always provide a manifest file describing the elements (as well as value providers, file initializers) contained in their DLL files. This will not only be helpful to developers, but would also be helpful to development tools.
I have provided such manifest files in the samples folder.