十年前,当我在一个企业级项目里首次接触Silverlight时,这个微软推出的RIA(富互联网应用)框架正处在巅峰时期。它让开发者能够创建媲美桌面应用的网页体验,支持高清视频流、复杂动画和离线功能。虽然现在主流浏览器已不再支持Silverlight插件,但仍有大量遗留系统依赖这项技术,特别是在医疗影像、金融交易和企业内部系统领域。
最近整理硬盘时发现当年积累的几十篇技术笔记,决定系统梳理这个曾经改变Web开发格局的技术体系。本文将涵盖从基础架构到高级特性的完整知识图谱,包含我在实际项目中验证过的解决方案和踩过的坑。无论你是需要维护遗留系统,还是单纯对技术演进感兴趣,这些经验都值得参考。
Silverlight的核心是一个跨浏览器插件,其架构分为三层:
与Flash相比,Silverlight的最大优势是完整支持.NET类型系统。我在医疗影像项目中就利用这个特性,将桌面端的DICOM解析库直接移植到Web端。运行时通过浏览器插件加载.xap包(本质是zip压缩的DLL集合),由CoreCLR在沙箱中执行。
重要提示:现代浏览器已默认禁用NPAPI插件,若需测试需使用IE兼容模式或专用虚拟机
当前可用的最后稳定版本是Silverlight 5:
配置示例(VS2019):
xml复制<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="...">
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\v5.0\Microsoft.Silverlight.CSharp.targets" />
<PropertyGroup>
<TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
</PropertyGroup>
</Project>
Silverlight的布局系统基于:
金融仪表盘项目中的经典布局结构:
xml复制<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="实时行情" Style="{StaticResource HeaderStyle}"/>
<Button Content="刷新" Click="RefreshData"/>
</StackPanel>
<Grid x:Name="ChartArea" Grid.Row="1">
<!-- 动态生成的K线图 -->
</Grid>
</Grid>
性能优化要点:
Silverlight的数据绑定系统支持:
股票交易系统的实时报价绑定示例:
csharp复制public class QuoteViewModel : INotifyPropertyChanged {
private decimal _price;
public decimal Price {
get => _price;
set {
if(_price != value) {
_price = value;
OnPropertyChanged();
// 触发价格变化动画
}
}
}
// 实现INotifyPropertyChanged...
}
XAML绑定配置:
xml复制<TextBlock Text="{Binding Price, StringFormat=C2, Mode=OneWay}"
Foreground="{Binding PriceChange, Converter={StaticResource ColorConverter}}"/>
Silverlight 5支持通过COM与本地应用交互(需提升信任级别):
csharp复制dynamic excel = AutomationFactory.CreateObject("Excel.Application");
excel.Visible = true;
excel.Workbooks.Add();
安全注意事项:
医疗影像系统的DICOM渲染流程:
csharp复制void ApplyWWWL(WriteableBitmap bitmap, int windowWidth, int windowCenter) {
int[] pixels = bitmap.Pixels;
for(int i=0; i<pixels.Length; i++) {
byte value = (byte)Math.Max(0, Math.Min(255,
(pixels[i] - windowCenter + windowWidth/2) * 255 / windowWidth));
pixels[i] = (255 << 24) | (value << 16) | (value << 8) | value;
}
bitmap.Invalidate();
}
某保险公司系统的迁移步骤:
推荐架构:
code复制原Silverlight功能 替代方案
---------------- --------
XAML UI Blazor/WPF
.NET Framework .NET 6+
WCF服务 gRPC/WebAPI
IsolatedStorage IndexedDB
迁移工具链:
跨域问题解决方案:
xml复制<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
内存泄漏定位:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| UI卡顿 | 过多动画同时运行 | 使用CompositionTarget渲染 |
| 加载缓慢 | XAP包过大 | 按需加载程序集 |
| 内存持续增长 | 数据绑定未清理 | 实现INotifyPropertyChanged |
遗留系统的CI/CD配置要点:
yaml复制# Azure Pipeline示例
steps:
- task: MSBuild@1
inputs:
solution: '**/*.csproj'
platform: 'AnyCPU'
configuration: 'Release'
msbuildArguments: '/p:TargetFrameworkVersion=v5.0'
- task: CopyFiles@2
inputs:
SourceFolder: '$(Build.SourcesDirectory)/Bin/Release'
Contents: '*.xap'
TargetFolder: '$(build.artifactstagingdirectory)'
必须实施的策略:
csharp复制bool VerifyAssembly(Assembly asm) {
var pubKey = asm.GetName().GetPublicKey();
using(var sha = new SHA256Managed()) {
return knownHashes.Contains(
Convert.ToBase64String(sha.ComputeHash(pubKey)));
}
}
在维护某银行交易系统的五年间,最深刻的体会是:Silverlight应用的稳定性极度依赖运行环境的一致性。我们最终为所有终端部署了定制版Chrome 45,并冻结了.NET Framework 4.5.2的补丁级别。对于必须保留的Silverlight模块,建议将其封装为WebView2控件,通过Edge渲染引擎提供长期支持。