1.     Inproc-SxS简介

InProc-SxS是.Net 4.0新推出的功能。在.Net 2.0中,一个进程中只能运行一个版本的.Net的运行时(Runtime)。在.Net 4.0中,我们可以在一个进程中运行多个不同版本的.Net运行时。也就是说在.Net 4.0,我们可以把进程的一部分的运行在.Net 4.0上,而另一部分运行在.Net 2.0上。我们可以把进程、运行时和程序域(AppDomain)用一个图来表示:

引入Inproc-SxS,给我们构建应用程序带来了很大的灵活性。在很多大型软件中,都允许第三方开发商添加插件(Add-in)。有了Inproc-SxS之后,不同的插件就可以运行在不同的.Net运行时上了。

比如一个软件开发商推出了一个基于.Net 4.0的软件,另一第三方软件开发商开发了该软件的一个插件。该插件的开发商还没有升级到.Net 4.0,仍然基于.Net 2.0开发软件,因此他们的插件还没有在4.0上做过任何测试。如果没有Inproc-SxS,该插件和它的宿主(Host)软件一样,都运行在.Net 4.0。由于插件并没有在4.0下测试过,运行在4.0运行时中就可能会有问题。现在有了Inproc-SxS,我们可以把宿主软件运行在.Net 4.0上,而插件运行在.Net 2.0上。

可能有人会问:.Net应该做到向下兼容,那基于.Net 2.0开发的插件在4.0上运行怎么会有问题呢?的确,微软的.Net 相应的开发团队在向下兼容性方面做了大量的工作。但100%的向下兼容只可能是一个理论上的目标。实际上在推出一个新版本的时候,总会对上一个版本会有若干不兼容的改动。如果用户在某一特定功能上仍然需要上一个版本,他可以利用Inproc-SxS把该功能单独运行在上一个版本的.Net中。

2.     Inproc-SxS实例

下面通过一个实例来讨论如何在Winforms中应用Inproc-SxS。这个实例分为三部分:第一部分是Winforms插件,第二部分负责把插件在某一特定版本的.Net中运行,第三部分是一个宿主应用程序。

2.1 Winforms插件

如下图所示,我们在一个UserControl(class名为CLRVersionControl)里添加一个GroupBox,一个Label和一个PropertyGrid:

为了演示需要,我们在Load的事件处理器(Event Handler)中,把GroupBox的Text设为当前程序域的名字,而把Label的Text设为当前.Net运行时的版本:

private void CLRVersionControl_Load(object sender, EventArgs e)

{

groupBox1.Text = AppDomain.CurrentDomain.FriendlyName;

label1.Text = "CLR version: " + Environment.Version.ToString();

}

同时,我们添加一个函数,用来生成该插件的一个实例,并返回该插件的句柄(Handle)。它的宿主应用程序可以通过该函数创建一个插件,并把该插件添加到宿主中。

public static IntPtr CreateCLRVersionControl()

{

Control control = new CLRVersionControl();

return control.Handle;

}

2.2 运行某版本的.Net

这一部分的功能分为两部分:首先我们要创建某一版本的.Net运行时;接着我们在.Net运行时中创建一个程序域的实例,并在该程序域中创建一个插件的实例。

.Net提供了接口ICorRuntimeHost、ICLRMetaHost和 ICLRRuntimeInfo来运行某一版本的.Net。下面是一段代码范例。读者可以查阅MSDN对应的帮助文档,我在此不再详细介绍这些API。

CComPtr<ICorRuntimeHost> LoadRunTime(LPCWSTR strVersion)

{

CComPtr<ICorRuntimeHost> runtimeHost = NULL;

CComPtr<ICLRMetaHost> metahost;

CComPtr<ICLRRuntimeInfo> rtInfo;

HMODULE hmscoree = LoadLibrary(L"mscoree.dll");

if(hmscoree == NULL) return NULL;

PGETCLRMETAHOST getClrMetaHost = (PGETCLRMETAHOST)GetProcAddress(hmscoree,

"GetCLRMetaHost");

if(getClrMetaHost == NULL) return NULL;

HRESULT hr = getClrMetaHost(__uuidof(ICLRMetaHost), (LPVOID*)&metahost);

if(SUCCEEDED(hr))

{

hr = metahost->GetRuntime(strVersion,

IID_ICLRRuntimeInfo,

(LPVOID*)&rtInfo);

if(SUCCEEDED(hr))

{

hr = rtInfo->GetInterface(CLSID_CorRuntimeHost,

IID_ICorRuntimeHost,

(LPVOID*)&runtimeHost);

if(SUCCEEDED(hr))

{

hr =  runtimeHost->Start();

if(FAILED(hr)) runtimeHost.Release();

}

}

}

if(hmscoree) FreeLibrary(hmscoree);

if(FAILED(hr))

{

MessageBox(NULL, L"CLR Load Failed", L"WinFormsSxSTest", MB_OK);

}

return runtimeHost;

}

我们在上述代码中输入某一个.Net的版本号,就能得到该版本号对应的.Net运行时。接下来我们在一个.Net运行时里创建一个程序域,并创建一个Winforms插件的实例:

int CreateControl(CComPtr<ICorRuntimeHost> runtimeHost,

LPCWSTR strAppDomainName,

LPCWSTR strAssemblyName,

LPCWSTR strTypeName,

LPCWSTR strMethodName)

{

CComPtr<IUnknown> punkAD;

HRESULT hr = runtimeHost->CreateDomain(strAppDomainName, NULL, &punkAD);

int retValue = 0;

if(SUCCEEDED(hr))

{

CComPtr<mscorlib::_AppDomain> srpAD;

hr = punkAD.QueryInterface(&srpAD);

if(SUCCEEDED(hr))

{

long hashCode = 0;

srpAD->raw_GetHashCode(&hashCode);

}

if(SUCCEEDED(hr))

{

CComPtr<mscorlib::_Assembly> srpAsm;

CComBSTR asmName = strAssemblyName;

hr = srpAD->raw_Load_2(asmName, &srpAsm);

if(SUCCEEDED(hr))

{

CComPtr<mscorlib::_Type> srpType;

CComBSTR typeName = strTypeName;

hr = srpAsm->raw_GetType_2(typeName, &srpType);

if(SUCCEEDED(hr) && srpType != NULL)

{

CComBSTR methodName = strMethodName;

CComVariant varEmpty, varRet;

hr = srpType->raw_InvokeMember(methodName,

(mscorlib::BindingFlags)

(mscorlib::BindingFlags_InvokeMethod |

mscorlib::BindingFlags_Public |

mscorlib::BindingFlags_Static),

NULL, varEmpty, NULL, NULL, NULL, NULL, &varRet);

retValue = varRet.llVal;

}

}

}

}

if(FAILED(hr))

{

MessageBox(NULL, L"WinForm Load Failed", L"Error", MB_OK);

}

return retValue;

}

上述代码用调用ICorRuntimeHost::CreateDomain在某版本的.Net运行时中创建一个程序域,让后在该该程序域中调用CLRVersionControl.CreateCLRVersionControl创建Winforms插件CLRVersionControl的一个实例。

有了前面的准备,我们就可以在一个特定的运行时里创建运行CLRVersionControl的实例:

extern "C" __declspec (dllexport) int __stdcall CreateCLRVersionControl

(

LPCWSTR strVersion,

LPCWSTR strAppDomainName,

LPCWSTR strAssemblyName,

LPCWSTR strTypeName,

LPCWSTR strMethodName

)

{

CComPtr<ICorRuntimeHost> runtimeHost = LoadRunTime(strVersion);

return CreateControl(runtimeHost,

strAppDomainName,

strAssemblyName,

strTypeName,

strMethodName);

}

2.3宿主应用程序

创建一个基于对话框的MFC项目,在该对话框上添加两个Button,如下图所示:

为第一个button的click添加响应函数:

CWnd* pWndNET2Controls;

void CApplicationHostDlg::OnBnClickedButton1()

{

if(pWndNET2Controls != NULL)

return;

int handle = CreateCLRVersionControl(L"v2.0.50727",

L"AppDomain A",

L"WindowsFormsControlLibrary1",

L"InProcSxSDemo.CLRVersionControl",

L"CreateCLRVersionControl");

pWndNET2Controls = new CWnd();

pWndNET2Controls->Attach((HWND)handle);

pWndNET2Controls->SetParent(this);

// set size and position

……

}

在上述代码中,v2.0.50727是.Net 2.0的版本号。我们根据返回的插件句柄创建一个窗口,并将该插件的窗口作为子窗口添加到对话框中。

同样我们也为第二个button添加click的响应函数:

CWnd* pWndNET4Controls;

void CApplicationHostDlg::OnBnClickedButton2()

{

if(pWndNET4Controls != NULL)

return;

int handle = CreateCLRVersionControl(L"v4.0.21002",

L"AppDomain B",

L"WindowsFormsControlLibrary1",

L"InProcSxSDemo.CLRVersionControl",

L"CreateCLRVersionControl");

pWndNET4Controls = new CWnd();

pWndNET4Controls->Attach((HWND)handle);

pWndNET4Controls->SetParent(this);

// set size and position

……

}

V4.0.21002是.Net 4.0 Beta2的版本号。读者安装了的.Net 4.0的版本号可能会有所不同,请做相应修改。和前面一样,我们也将插件的窗口作为子窗口添加到对话框中。

现在我们运行我们宿主软件,并先后点击两个button,得到如下效果:

通过上面的截图,我们可以看出来,左边的插件时运行在.Net 2.0中,而右边插件运行在.Net 4.0中。如果仔细观察,我们还能发现在两个插件的PropertyGrid中略有不同:左边的PropertyGrid用+或者-来表示树状结点的打开或者收拢的状态,而右边的PropertyGrid用风格的三角形来表述树状结点的状态。这是因为在.Net 4.0中,Winforms对PropertyGrid做了一点改动,使PropertyGrid的树状结构和Vista、Windows 7的风格保持一致。

Winforms:在Winforms中应用Inproc-SxS相关推荐

  1. web.config中的InProc模式 与 StateServer模式[转]

    开发asp.net应用时,修改web.config中的SessionState节点. stateserver模式: <sessionState mode="StateServer&qu ...

  2. .NET Core 3.0中的WinForms创建集中式拉取请求中心

    Windows 窗体(或简称 WinForms),多年来被用于开发具有丰富和交互式界面的基于 Windows 的强大应用程序. 各类企业对这些桌面应用程序的投入量非常巨大,每月有大约 240 万开发人 ...

  3. 解决vs2019中暂时无法为.net core WinForms使用 Designer 的临时方法

    以下方法来自于微软github开源项目WinForms: dotnet/winforms - Using the Classic WinForms Designer in WinForms Core, ...

  4. DevExpress v19.1新版亮点——WinForms篇(五)

    行业领先的.NET界面控件DevExpress v19.1终于正式发布,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WinForms v19.1中新增的一些控 ...

  5. DevExpress WinForms使用教程:图表控件 - 内置深入查询

    [DevExpress WinForms v18.2下载] 在最新发布的DevExpress WinForms v18.2中,DevExpress WinForms和ASP.NET图表控件引入嵌套系列 ...

  6. DevExpress WinForms Controls v22.1 beta版来袭,上车

    DevExpress v22.1 beta版本已经上线,让我们一起先睹为快,看看将会有哪些内容更新?  新的WXI皮肤 我们的新WXI皮肤(主题)基于Windows 11.WXI皮肤附带五种调色板:& ...

  7. DevExpress WinForms — 2021 产品路线图

    DevExpress 官方提供的2021年产品路线图计划,让我们一起来预览一下吧. DevExpress预计在 2021 年发布的新的控件和性能增强功能外,我们希望分配大量资源,帮助缩小 WinFor ...

  8. DevExpress WinForms使用教程:WinForms Fluent Design和Acrylic Effects

    在先前的版本发布中,宣布支持Fluent Design Form和Acrylic effects--旨在复制Microsoft下一代UI metaphor的新功能.本文主要介绍如何实现此功能,并明确说 ...

  9. GOA WinForms 系列

    介绍一个来至比利时的公司的免费产品,GOA WINFORMS. 有时一些其他的应用需求,让人头疼(比如Flash).而现在可以专注于C#,一样能完成Flash的需求. 该公司还有提供第三方的Silve ...

  10. 整合.NET WebAPI和 Vuejs——在.NET单体应用中使用 Vuejs 和 ElementUI

    .NET简介 .NET 是一种用于构建多种应用的免费开源开发平台,例如: Web 应用.Web API 和微服务 云中的无服务器函数 云原生应用 移动应用 桌面应用 1). Windows WPF 2 ...

最新文章

  1. linux c 获取文件行数
  2. 802.11n标准简介
  3. ioread32函数有关知识
  4. headfirstjava最新版本下载_读过HeadFirstJava的大神进来看看
  5. mysql gtid模式主键主突_Mysql基于GTID主从复制
  6. SDN第5次上机作业
  7. Google 发布其非 Linux 系操作系统 Fuchsia 说明书!
  8. 10-20C#基础---一维、二维数组冒泡排序
  9. 没有基础的人可以学python吗-没有任何基础的人,该如何学习Python?「附具体步骤」...
  10. C++程序设计(三:可视化)
  11. HTML5 Web Storage
  12. ns.ajax,UIWebView使用NSURLProtocol(拦截),ajax加载失败的问题
  13. 节奏大师服务器不稳定,节奏大师无法登陆的原因及解决方法
  14. UML 用例图符号含义
  15. 【Docker 那些事儿】如何安全地停止、删除容器
  16. 随机产生四位,任意位或者范围数字方法
  17. Python基础教程(第三版)
  18. CAST和CONVERT
  19. Delphi 函数使用技巧
  20. windows开启远程桌面,防火墙拦截:只允许特定IP远程

热门文章

  1. vue实现性别选择框
  2. 把苹果全家桶用于VR全身追踪是什么体验
  3. 【C++】多继承的多态
  4. Excel 2010 SQL应用028 查询空值
  5. D. AB-string(对立事件)
  6. unity 手写板 截取游戏画面 识别手写文字 全家桶
  7. 归梦序曲,幻想延续 —— 宫崎骏《起风了》影评
  8. python任务栏_Python 将窗口嵌入到任务栏,在任务栏显示文本
  9. 测试工具篇:postman技巧
  10. 新浪博客发表博文不同步到新浪微博