Inside Portable Class Libraries
Portable Class Libraries were introduced with Visual Studio 2010 SP1 to aid writing libraries that could be used on many different platforms – the full .NET 4/4.5 framework, Windows Phone, Silverlight, Xbox, and Windows Store apps. You simply select which platforms and versions you want to target, then the available subset of APIs are magically available. But how does it work? How does Visual Studio know what it can target, and how does the same assembly run on many different platforms? Today, I’ll be finding out.
Creating a Portable Class Library
When you create a PCL in Visual Studio, you select the platforms and versions you want to target. In this example, I’ve selected everything at the lowest available version. In the project references list, this turns into a generic ‘.NET Portable Subset’, with no real identifying information as to what it actually is:

Hmm, ok, well lets see what the actual built assembly does with it. Lets create a field of type Action<T1,T2> so the assembly actually has something in it:
public class Class1 {
Action<int, double> action = null;
}
After building the assembly, and opening it up in a decompiler, we can see that that mysterious ‘.NET Portable Subset’ reference has turned into standard assembly references to mscorlib.dll and System.Core.dll. However, they look a bit odd:
mscorlib, Version=2.0.5.0, Culture=neutral,
PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes
System.Core, Version=2.0.5.0, Culture=neutral,
PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes
2.0.5.0 is the version number used by Silverlight assemblies, and that’s the Silverlight public key, but that ‘Retargetable’ flag is new. And if you have a look at the assembly-level attributes, you’ll spot something familiar:
[assembly: TargetFramework(
".NETPortable,Version=v4.0,Profile=Profile1",
FrameworkDisplayName=".NET Portable Subset")]
Aha! There’s the ‘.NET Portable Subset’ from the Visual Studio reference list. But what about the target framework? ".NETPortable,Version=v4.0,Profile=Profile1"? What’s that all about? Well, have a look in ‘C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\’. In there is a list of every possible .NET 4 PCL subset you can target (22 in total). Within each profile directory are the available assemblies containing the types that can be used, and an xml file for each framework supported by that profile containing platform version information.
These profile directories have been pre-calculated by Microsoft and installed alongside visual studio. When you create a PCL project, and select the platforms and versions you want supported, Visual Studio looks at all the available profiles and the framework versions they are valid for. From the version and platform information in each profile it works out the most applicable profile, and dlls in that profile are the ones it compiles the PCL assembly against and to provide intellisense support.
But these dlls are useless at runtime. If you open one of the dlls in a decompiler, you’ll see that all the method bodies are empty or simply return the default value for the return type. These dlls exist only to be referenced and compiled against.
Using a portable class library
So the dlls in the Reference Assemblies folder are, rather unsuprisingly, only to be referenced. Something else happens at runtime to make the portable library work on all the supported frameworks.
It turns out that it all comes down to a feature of .NET assemblies that was introduced in .NET 2, and I looked at two years ago – type forwards. In the portable class library I’ve built, the System.Action`2 type I’ve used has been resolved to the System.Core assembly. In different platforms, it may be in different places. But every platform will either contain the type in System.Core, or System.Core will have a type forward to where the type is actually located.
So, as you’ll see in the framework-specific reference assemblies, Silverlight 4, Windows Phone, and Xbox all have System.Action`2 located in their System.Core.dll, so the type is resolved successfully on those platforms. Both the desktop and Silverlight 5 System.Core.dll have a type forward for System.Action`2 to the relevant mscorlib.dll, where the type is actually located.
Windows store applications (the framework for windows store applications is called ‘.NETCore’) forward the type to System.Runtime.dll. And, if you take a further look at the System.Core.dll in the .NETCore framework, this assembly contains no types whatsoever! The only things in that assembly of any note are a series of type forwards to various other assemblies in the .NETCore framework – that assembly exists only to redirect type references in portable class libraries when they are used in Windows Store applications.
Cross-version assembly references
There is one more thing we need to sort out. If you have a look at the assembly references in the original PCL we built, they reference a specific version of mscorlib.dll and System.Core.dll:
mscorlib, Version=2.0.5.0, Culture=neutral,
PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes
System.Core, Version=2.0.5.0, Culture=neutral,
PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes
These versions are the same as the version numbers on Silverlight 4, Windows Phone, and Xbox framework assemblies. But the version of mscorlib for Silverlight 5 is:
mscorlib, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
and .NET 4 desktop and .NETCore:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
This is a problem. These assemblies all have strong name signatures, and the version & public key form part of the assembly’s identity. An assembly reference to an assembly with version 2.0.5.0 and public key 7cec85d7bea7798e cannot be resolved to an assembly with version 4.0.0.0 and public key b77a5c561934e089. To the CLR, these are two completely different assemblies.
That’s where the Retargetable flag on the assembly references comes in. If this flag is on an assembly reference, it means the reference can resolve to an assembly with a different version and public key, even though it is technically a different assembly. This flag is on all the references to framework dlls in a PCL, and this means the PCL can run on different frameworks with different assembly versions and public keys. The framework dll references are resolved to the one available in the framework the library is executing on at runtime.
Conclusion
There’s nothing magic about portable class libraries. They are compiled just like any other assembly, but are compiled against a specific pre-defined subset of the libraries available in the different frameworks, defined by portable profiles representing the various combinations of types and methods available. When the library is executing on a specific framework at runtime, type fowards redirect any types that have been moved to a different assembly in that framework. The common CLR, assembly metadata and IL formats across all the frameworks and versions ensure the actual code logic in the assembly executes the same way on any available framework.
from:https://www.simple-talk.com/blogs/2013/04/19/inside-portable-class-libraries/
Inside Portable Class Libraries的更多相关文章
- How to Make Portable Class Libraries Work for You
A Portable Class Library is a .NET library that can be used (in binary form, without recompiling) on ...
- The .NET of Tomorrow
Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciting times lie ahead f ...
- DotNet 资源大全中文版(Awesome最新版)
Awesome系列的.Net资源整理.awesome-dotnet是由quozd发起和维护.内容包括:编译器.压缩.应用框架.应用模板.加密.数据库.反编译.IDE.日志.风格指南等. 算法与数据结构 ...
- A Complete List of .NET Open Source Developer Projects
http://scottge.net/2015/07/08/a-complete-list-of-net-open-source-developer-projects/?utm_source=tuic ...
- [译]Introducing ASP.NET vNext and MVC 6
原文:http://www.infoq.com/news/2014/05/ASP.NET-vNext?utm_source=tuicool Part of the ASP.NET vNext init ...
- visual studio 2013 配置开发环境
https://www.visualstudio.com/explore/xamarin-vs http://sourceforge.net/projects/easyeclipse/files/?s ...
- Introducing ASP.NET vNext and MVC 6
[译]Introducing ASP.NET vNext and MVC 6 原文:http://www.infoq.com/news/2014/05/ASP.NET-vNext?utm_source ...
- .NET 开源开发项目【翻译】
原文地址 本文列出了 .NET 开源开发项目(open source developer projects).意在包括对开发过程的所有方面有所帮组的项目.对于消费项目(consumer project ...
- Go 2 Draft Designs
Go 2 Draft Designs 28 August 2018 Yesterday, at our annual Go contributor summit, attendees got a sn ...
随机推荐
- Python基础 - Ubuntu+Nginx+uwsgi+supervisor部署Flask应用
网上找了许多讲关于Flask应用部署的文章几乎都是一个helloworld的Demo,按照helloworld来部署都没问题,但实际项目部署时还是遇到了不少问题.在这里简单写下自己成功部署的过程,防止 ...
- jersey 过滤器名称绑定的问题 NameBinding Provider
查资料也不容易查,这个问题困扰了我两天. 当没有 @Provider 的时候 过滤器不会被执行.
- xcode7 调用相册权限无提示
1) 打开工程的Info.pilst: 2) 把 Bundle name 和 Bundle display name 的 value值 ,改成跟项目app名一致: 这样系统才能正确地接收到调用请求
- linux 系统网卡无法识别,缺少驱动
#linux网卡驱动安装# Linux设备加载 #lsmod Module Size Used by e1000e 查看硬件设备 ls /usr/share/hwdata 查看pci网卡设备 lspc ...
- HA下的Spark集群工作原理解密
实验环境: zookeeper-3.4.6 Spark:1.6.0 简介: 本篇博客将从以下几点组织文章: 一:Spark 构建高可用HA架构 二:动手实战构建高可用HA 三:提交程序测试HA 一:S ...
- 企业级Docker Registry —— Harbor搭建和使用
本节内容: Harbor介绍 安装部署Harbor 环境要求 环境信息 安装部署harbor 配置harbor 配置存储 完成安装和启动harbor 访问Harbor 修改管理员密码 启动后相关容器 ...
- 易普优APS混流排序算法助力汽车整车厂的均衡生产
一.汽车整车厂生产排序的难点 “ 冲压-焊接-涂装-总装”是汽车整车生产的四大工艺类型,它们存在上下游关联关系,每个车间都有自己的优化排序目标,汽车混流生产模式使得生产过程更加复杂,从而生产管控的难度 ...
- Educational Codeforces Round 56 (Rated for Div. 2) F - Vasya and Array dp好题
F - Vasya and Array dp[ i ][ j ] 表示用了前 i 个数字并且最后一个数字是 j 的方案数. dp[ i ][ j ] = sumdp [i - 1 ][ j ], 这样 ...
- python之markdown转html
python之markdown转html 为了方便,定义一个markdown转html的函数,直接调用即可 import markdown def md2html(mdstr): exts = ['m ...
- java 代码中设置 临时 环境变量
System.setProperty("hadoop.home.dir", "D:\\software\\software_install\\dev_install\\h ...