Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Monday, 21 September 2015

Universal-Windows-Platform-SmallI recently made an interesting discovery about Universal Windows Platform apps.

When you build and run them in Release mode they are compiled using the .NET Native compiler, and they stop using mscorlib.

Most of your common .NET types come out of mscorlib. For example:

System.Object, mscorlib, Version=4.0.0.0, Culture=neutral,PublicKeyToken=7ce85d7bea7798e

When you are running UWP code in Debug mode that remains true. But in Release mode the use of mscorlib is replaced by System.Private.CoreLib. For example:

System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

In the vast majority of cases nobody cares about the assembly qualified name of a type – unless you are using reflection, in which case you may easily make this same discovery.

In my case, working on CSLA .NET, this difference posed a real challenge. One of the key features of CSLA is the concept of mobile objects, where object graphs transparently flow (move) across the tiers of your application (between AppDomains, processes, or computers over the network). For this to work, the type names of the objects must be the same in the source and destination environments, whether that be an Android client talking to a full .NET server, or a UWP client talking to that same server.

Fortunately ever since ~2007 and Silverlight’s restrictions on reflection (and the fact that it didn’t support BinaryFormatter or NetDataContractSerializer) CSLA has had its own serializer: MobileFormatter.

MobileFormatter has some serious advantages over BinaryFormatter and the NDCS, most notably it works across all platforms in a consistent manner, as well as minimizing the use of reflection and providing substantial control over the format of the byte stream transferred over the network.

In this scenario that last point is important, because I was easily able to enhance MobileFormatter to translate any assembly qualified type name that uses mscorlib or System.Private.CoreLib so the assembly name is an arbitrary text code. I chose /n. The full assembly name becomes /n during serialization, and that code becomes the full assembly name during deserialization.

The result is that types flow between UWP and all other platforms (.NET, Xamarin, etc.) transparently - as always. As a bonus this change reduces the number of bytes transferred over the wire because the full assembly name isn't in the byte stream, just this short code.

I found that benefit to be compelling enough that while I was changing MobileFormatter to solve the mscorlib issue I also added code to translate the CSLA assembly name to /c in the same manner.

In the future I may look at ways to translate user-created assembly names (your business assemblies) into short codes as well, as that would save a lot of bytes on the wire.

Monday, 21 September 2015 15:47:28 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Wednesday, 16 September 2015

Steps to repro the issue described in this github issue:

https://github.com/MarimerLLC/csla/issues/428

1. Pull the csla repo from
https://github.com/rockfordlhotka/csla.git

a. Switch to the NuGet-uwp branch
clip_image001

2. Open <root>\csla\Source\csla.build.sln

a. Build Release | All CPU
clip_image002

b. Don’t worry about the Xamarin projects – they don’t matter for this issue

c. Build results will be in <root>\csla\bin

i. including the problematic rd.xml files for the UWP projects

3. Open PowerShell, cd to <root>\csla\NuGet

a. Run ‘Build All.ps1’ /prerelease:Beta3

b. Run consolidatepackages.bat

4. Open <root>\csla\Samples\ProjectTracker\ProjectTracker.sln

a. Add a NuGet package source to <root>\Packages, for example:
clip_image004

b. Build Debug | All CPU

i. Ignore the async method lacks await warning – this is a testing artifact

ii. Ignore the warnings about our analyzers (unless you know how to fix them – this analyzer via NuGet stuff is challenging at best!!!!)

iii. You should end up with a build error:

Severity

Code

Description

Project

File

Line

Error

 

Payload contains two or more files with the same destination path 'Csla\Properties\Csla.Uwp.rd.xml'. Source files: C:\Users\Rockford\.nuget\packages\CSLA-Core\4.6.172-Beta3\lib\uap10.0\Csla\Properties\Csla.Uwp.rd.xmlC:\Users\Rockford\.nuget\packages\CSLA-UWP\4.6.172-Beta3\lib\uap10.0\Csla\Properties\Csla.Uwp.rd.xml

ProjectTracker.Ui.UWP

   

Wednesday, 16 September 2015 11:00:21 (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, 04 September 2015

In a recent blog post @praeclarum discusses frustrations with NuGet 3.

His viewpoint is from someone who uses (used?) PCLs.

What is interesting is that I agree with him about NuGet 3, but my viewpoint is as someone who chose Shared Projects over PCLs.

So I rather suspect NuGet 3 solved some unknown set of problems that somebody must have had – but it wasn’t authors of libraries using and not using PCLs. Huh.

You might ask why I don’t use PCLs – and in particular in my CSLA .NET framework, which is extremely cross platform. And that’s actually part of the answer.

CSLA .NET came into being before .NET itself was released, and has been evolving ever since. Perhaps the biggest point of evolution occurred when I chose to support Silverlight 2.0 in around 2006 (or 2007?). That was the first point where the (then years old) codebase needed to stop depending on full .NET. Also at that point in time neither PCLs nor Shared Projects existed, but Linked Files existed (the precursor to Shared Projects).

As a result, much of the CSLA Silverlight code existed as links to files in the full CSLA .NET project. So there were two different projects – one for .NET and one for Silverlight. Shortly followed by a third project when .NET Server and .NET Client split.

Of course the .NET and Silverlight platforms weren’t the same, but by using linked files each shared file was compiled for each target platform, and we were able to use compiler directives to accommodate differences in each platform.

Any real-world project tends to end up with some cruft, and CSLA is no exception. By the time we’d followed this model to add Silverlight, Windows Phone, various versions of .NET (3.5, 4, 4.5), Xamarin (iOS and Android aren’t always identical either), WinRT, and mono we’d accidentally duplicated various files and inappropriately reused some compiler directives. I wish I could say the CSLA dev team was perfect at all times, but we take shortcuts, or miscommunicate, from time to time like anyone else.

Earlier this year I undertook a major initiative to shift all the linked files into a set of common Shared Projects using the official support provided in Visual Studio 2015. The end result is really nice, but this change brought me face to face with every compromise or mistake we’d made over the past several years. Fun!

The end result is that all the actual code for CSLA resides in a small set of Shared Projects, and those projects are shared into concrete compilable projects for each target platform supported by CSLA .NET. The release folder (compiler output target) looks like this:

snip_20150904183300

Then a set of NuGet 2 packages are created representing the various scenarios where people would want to use CSLA to reuse their business logic – across different user experiences and/or different platforms. The list of NuGet packages includes:

  • Core (basically Csla.dll for your platform)
  • Web (Core + Web (basic ASP.NET and Web Forms helpers))
  • MVC (Core + Web + helpers for the MVC version you are using)
  • WPF (Core + WPF helpers)
  • WinForms (Core + Windows Forms helpers)
  • WinRT/UWP (Core + WinRT and UWP helpers – which are the same right now thankfully)
  • Android (Core + Android helpers)
  • iOS (Core + iOS helpers)
  • Entity Framework (Core + helpers for the EF version you are using)
  • Validation (Core + helpers for enable backward compatibility with an older rules engine from CSLA 3.8)
  • Templates (installs VS templates and snippets on the dev workstation)

To accomplish this we have the following solution structure for the core Csla.dll outputs:

snip_20150904184309

Notice that there’s one Csla.Shared project – it contains all the code – and then a set of concrete compilable projects for the various platforms and .NET versions supported. Those projects contain no code at all, just settings for the compilers.

Would a PCL simplify this? Sort of, but not really. There are too many differences between some of these target platforms for the actual implementation code to exist in a single PCL. Remember, you can’t use compiler directives or have any platform-specific implementation code in a PCL – and that constraint is just too limiting to allow CSLA to do what it does. Perhaps this is in large part because a key feature of CSLA is that it shields your business code from underlying platform differences, so we can’t dumb down the code in CSLA and allow platform differences to penetrate our abstractions or we’d lose a primary benefit of CSLA itself.

Namely, you write your business logic one time and then reuse that exact code on every platform you want to target, thus radically reducing your maintenance burden over the years you’ll be running that code.

Now there is the concept of “bait-and-switch” with a PCL, where the PCL itself contains no implementation – only public interface definitions. And then you create a concrete compilable project with the actual implementation for each platform and .NET version you want to support. In other words, you do exactly what we are doing here, with the addition of one more project that only contains all the public class/interface/type information from Csla.Shared.

And I might do this “bait-and-switch” hack someday – but to make such a thing manageable I’d want a tool I can run as part of the build process that generates all that public type information from Csla.Shared, because otherwise I’d have to maintain it all by hand and that’s just asking for trouble. (anyone knowing of such a tool feel free to let me know!!)

We follow the same basic pattern for the various UI technologies – so there are a similar set of concrete projects and one shared project for XAML, Android, iOS, Web, MVC, etc.

The result is, in my view, extremely manageable thanks to the great support for Shared Projects in Visual Studio 2015. Yes, we’ve been following this approach “the hard way” since ~2007, so I feel very confident saying that VS2015 is a major step forward in terms of tooling around this model.

I also feel comfortable saying that I have no regrets that we didn’t go down the PCL route when PCLs were introduced. They’d have required we use the “bait-and-switch” hack, which is too much magic for my taste, and I think they’d have further increased the complexity of our solution.

Back to NuGet 3 – nothing I’m talking about here requires (or currently uses) NuGet 3. Part of the build process generates a set of NuGet 2 packages that I push into NuGet:

snip_20150904185812

As a result, when you add a reference to ‘CSLA MVC5’ you get the correct ‘CSLA Core’, ‘CSLA Web’, and ‘CSLA MVC’ assemblies in your project for the version of .NET your projects are targeting. Exactly what you expect. Easy for the end developer, and I think easy for us as maintainers of an OSS library.

From what I can see, NuGet 3 just changes a bunch of stuff and adds confusion to fix some problems I’m not encountering. That’s never a good sign…

Friday, 04 September 2015 18:01:31 (Central Standard Time, UTC-06:00)  #    Disclaimer
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
February, 2017 (2)
January, 2017 (2)
December, 2016 (5)
November, 2016 (2)
August, 2016 (4)
July, 2016 (2)
June, 2016 (4)
May, 2016 (3)
April, 2016 (4)
March, 2016 (1)
February, 2016 (7)
January, 2016 (4)
December, 2015 (4)
November, 2015 (2)
October, 2015 (2)
September, 2015 (3)
August, 2015 (3)
July, 2015 (2)
June, 2015 (2)
May, 2015 (1)
February, 2015 (1)
January, 2015 (1)
October, 2014 (1)
August, 2014 (2)
July, 2014 (3)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017, Marimer LLC

Send mail to the author(s) E-mail



Sign In