Archive

Posts Tagged ‘Extensions’

How to compile code that uses WPF Decorator type in Silverlight

At ClipFlair I’m using a modified version of FloatingWindow control, where I try to make the WPF and Silverlight flavours of the original control share as much code as possible (this is work in progress currently, hoping to eventually have the WPF and Silverlight projects both link to the same source files [this is currently true for most of those files]).

With the ControlExtensions.cs file there (which has some useful extension methods for WPF and Silverlight controls), I had an issue, since they were very similar, apart from the fact that the WPF version had 2 methods that were using Decorator type in their implementation, whereas the Silverlight ones were identical apart from using the Border  type.

WPF’s Border class extends WPF Decorator, whereas Silverlight’s Border doesn’t since Silerlight doesn’t have a Decorator class at all (to keep the size small for quick web installation they cut-off needless parts of WPF, that’s why they call Silverlight a small sibling of WPF [used to all call WPF/E if I remember well]).

Seems there’s a quick trick one can pull out to overcome this, based on C# support for “Type Aliases” with the using directive. You can add to the problematic source code file (either outside or inside any namespace declaration you have there), the following:

#if SILVERLIGHT
using Decorator = System.Windows.Controls.Border;
#endif

Then in that source code file you just use Decorator instead of Border for both WPF and Silverlight. Of course this works in method bodies, if you want to have that type in method parameters else well, you have to put the above type alias definition (called Using Alias Directive) in every source code file that uses this class. I’d prefer to put this in my WPF_Compatibility layer at ClipFlair codebase, but C# support for type aliases is very limited unfortunately, so I put a dummy WPF_Delegate.cs file there with the above usage info.

Isn’t it sad that you can place extension methods in existing namespaces, but can’t place type aliases similarly? In fact you can’t place say some of them in a file and refer to them alltogether, you have each user of your types replicate those using definitions to all code units where they use them. If you change somethine in the future in those definitions, things will break since some files will have outdated definitions (apart from having consumers of your types see unnecessary implementation details). I guess we need Alias Types, not Type Aliases (sic).

To see this in action, you can try opening in Visual Studio the FloatingWindow solution under Client folder of http://clipflair.codeplex.com source code base. You’ll notice the file Extensions/ControlExtensions.cs has a small arrow icon on it at both the Silverlight and the WPF projects, since it’s a link (added to both the projects using Add Existing File and clicking the dropdown menu next to the Add button to select “Add as Link”).

Speaking of file links in Visual Studio 2010, there seems to be a bug there. If you remove (not delete) a file from a project, then move that source file to another location (say one folder higher and into a Common subfolder), you can’t add the file to the project anymore till you Close the project (or right-click and Unload it) and Open it again (or reload it into the current Solution).

Why I don’t see static extension support for constructors in C# coming

I was hoping C# would someday add static extension support for constructors too (apart from classic methods), that would help a lot in source-level compatibility layers (for example at my WPF_Compatibility project for WPF syntax in Silverlight, which one can find under the ClipFlair source base).

However, according to :

http://mrpmorris.blogspot.gr/​2007/01/​net-calling-base-constructors-i​n-c.html

Anders Hejlsberg (father of Delphi and C#) said in an e-mail:

The problem with Delphi’s model allowing constructors to be called on an already constructed object) is that it makes it impossible to have provably immutable objects. Immutability is an important concept because it allows applications to hand objects to an external party without first copying those objects and still have a guarantee that the objects won’t be modified. If constructors can be called on already constructed objects it obviously isn’t possible to make such guarantees. In Delphi’s case that may be ok since Delphi doesn’t really make type safety guarantees anyway (you can cast any object reference to a pointer-to-something and start poking away), but .NET goes further with type safety and this would be a big hole.

He was replying on why one can’t call an ancestor’s constructor directly in C#, but I guess this covers the case of injecting more constructors into ancestors via the static extension method mechanism of recent C# versions.

workaround: Silverlight Rect class missing ‘bool Contains(Rect)’ method

In ClipFlair, I’ve been looking into porting Kael Rowan’s ZoomableCanvas (related to ZUI code used in Code Canvas, Debugger Canvas etc. VisualStudio add-ons) from WPF to Silverlight.

One of the issues I found was that Silverlight’s Rect class (I guess this is a case for .NET Compact Framework in general) doesn’t have a method to check if a Rect contains another Rect, as does the full .NET framework which is available in WPF. That method was needed in Kael’s PriorityQuadTree source code.

Since we can check whether a Rect is contained in another Rect by checking if both its top-left and top-right points are contained, I edited Kael’s RectExtensions class, adding the following method:

/// <summary>
/// Indicates whether the current rectangle contains the specified rectangle, 
/// by checking for containment of the specified rectangle's top-left and
/// bottom-right points.
/// </summary> /// <param name="self">The current rectangle.</param> /// <param name="rect">The rectangle to check.</param> /// <returns><c>true</c> if the current rectangle contains the specified
/// rectangle; otherwise, <c>false</c>.</returns> public static bool Contains(this Rect self, Rect rect){ return self.Contains(new Point(rect.Left, rect.Top))
&& self.Contains(new Point(rect.Right, rect.Bottom)); }

Note that RectExtensions is a static (with only static methods, not instantiatable) class containing static extension methods (a feature of recent .NET versions), for the Rect class. So, once you’ve imported the RectExtensions class in a Silverlight class (assuming you have RectExtensions in the same project or in some referenced Silverlight or Portable library), all Rect instances gain a new method “bool Contains(Rect)” apart from the “bool Contains(Point)” one.

BTW, speaking of Zoomable User Interfaces (ZUIs) above, an important difference between WPF and Silverlight is that WPF has a theoretically unboundeded coordinate system, in contrast to Silverlight’s bounded one, where the maximum value for a coordinate component is approximately +32768. As stated in Microsoft’s WPF Compatibility article:

WPF has a theoretically unbounded coordinate system. Silverlight has a bounded coordinate system. The maximum value for a coordinate component in Silverlight is approximately +32678. APIs that represent a Silverlight coordinate might throw a native-level error or raise an exception if this maximum value is exceeded. This is true even for values that might be temporary and not intended for the final rendering value. 32678 is well beyond the maximum screen size, so this should only be an issue if you are performing math or applying transforms to coordinate values.

%d bloggers like this: