在Framework 4.0中:找出新增的方法与新增的类(二)
为什么动态加载程序集无法找出framework 4.0 和framwork2.0 新增的方法和类?
因为控制台程序默认就添加了framework4.0的程序集,当你使用object,type,string这些类的时候就已经在使用已经加载的程序集了,而clr不会重复的去加载程序集??,这点记不清了。
所以v2assembly 和v4assembly都是framework4.0的assembly。
验证:
static void main(string[] args)
{
assembly assemblyv2 = assembly.loadfile(
@"c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll");
assembly assemblyv4 = assembly.loadfile(
@"c:\windows\microsoft.net\framework\v4.0.30319\mscorlib.dll");
console.writeline("v2的名称{0}\nv4的名称{1}", assemblyv2.fullname, assemblyv4.fullname);
console.readline();
}
输出如下:
因为mscorlib.dll 是在share domain中的程序集,所以在同一应用程序中无法加载两个不同的mscorlib.dll.所以考虑使用两个应用程序,一个framework 2.0,另一个framework 4.0。
于是可以换个思路:使用2.0的framework来创建的程序来调用framework4.0的wcf服务。
代码结构如下:
v4newlooker是基于framework 2.0的winform程序
v4wcfservice是基于framework 4.0 的wcf服务。
接口的定义如下:
namespace v4wcfservice
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“iservice1”。
[servicecontract]
public interface iservice1
{
[operationcontract]
list<typemembers> getnewtypemember(list<typemembers> lstoldtypes);
}
[datacontract]
public class typemembers
{
[datamember]
public string fullname { get; set; }
[datamember]
public list<string> membernames { get; set; }
}
}
服务实现代码如下:
namespace v4wcfservice
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“service1”。
public class service1 : iservice1
{
public list<typemembers> getnewtypemember(list<typemembers> lstoldtypes)
{
list<typemembers> result = new list<typemembers>();
assembly mscorlibassembly = typeof(object).assembly;
type[] v4types = mscorlibassembly.gettypes();
#region 所有更新的type
foreach (typemembers v3type in lstoldtypes)
{
type v4type = v4types.firstordefault(t => t.fullname == v3type.fullname);
if (v4type != null && !v4type.isenum)
{
memberinfo[] v4mis = v4type.getmembers();
if (v4mis.length != v3type.membernames.count)
{
memberinfo[] v4newmis = v4mis.where(mi =>
!v3type.membernames.contains(mi.name)).toarray();
result.add(new typemembers()
{
fullname = v4type.fullname,
membernames = v4newmis.select(mi => mi.name).tolist()
});
}
}
}
#endregion
#region 所有新增的type
list<string> v3typefullname = lstoldtypes.select(tm => tm.fullname).tolist();
type[] v4newtypes = v4types.where(t => !v3typefullname.contains(t.fullname) &&
!t.isenum).toarray();
foreach (type v4newtype in v4newtypes)
{
result.add(new typemembers()
{
fullname = v4newtype.fullname,
membernames = v4newtype.getmembers().select(mi => mi.name).tolist()
});
}
#endregion
return result.orderby(tm=>tm.fullname).tolist();
}
}
}
服务的实现和第一个反射的版本差不多。
web.config文件绑定代码如下:
<system.servicemodel>
<bindings>
<wshttpbinding>
<binding name="newbinding0" maxreceivedmessagesize="65536000" />
</wshttpbinding>
<mexhttpbinding>
<binding name="newbinding1" />
</mexhttpbinding>
</bindings>
<services>
<service behaviorconfiguration="v4wcfservice.service1behavior"
name="v4wcfservice.service1">
<endpoint address="" binding="wshttpbinding" bindingconfiguration="newbinding0"
contract="v4wcfservice.iservice1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexhttpbinding" bindingconfiguration="newbinding1"
contract="imetadataexchange" />
</service>
</services>
<behaviors>
<servicebehaviors>
<behavior name="v4wcfservice.service1behavior">
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
<servicemetadata httpgetenabled="true"/>
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
<servicedebug includeexceptiondetailinfaults="false"/>
</behavior>
</servicebehaviors>
</behaviors>
</system.servicemodel>
因为默认的maxreceivedmessagesize 为65536,所以在后面增加了两个0, 否则会抛出经典的超出范围的异常。
winform程序界面如下:
后台代码如下:
namespace v4newlooker
{
public partial class form1 : form
{
public form1()
{
initializecomponent();
}
private list<typemembers> newtypemembers { get; set; }
private void btnsearch_click(object sender, eventargs e)
{
assembly mscorlibassembly = typeof(object).assembly;
list<typemembers> v3typemembers = new list<typemembers>();
foreach (type v4newtype in mscorlibassembly.gettypes())
{
list<string> membernames = new list<string>();
memberinfo[] mis = v4newtype.getmembers();
foreach (memberinfo mi in mis)
{
membernames.add(mi.name);
}
v3typemembers.add(new typemembers()
{
fullname = v4newtype.fullname,
membernames = membernames
});
}
using (service1client client = new service1client())
{
newtypemembers = client.getnewtypemember(v3typemembers);
}
list<string> typenames=new list<string>();
foreach (typemembers tm in newtypemembers)
{
typenames.add(tm.fullname);
}
lstbox_types.datasource = typenames;
}
private void lstbox_types_selectedindexchanged(object sender, eventargs e)
{
string fullname = lstbox_types.selecteditem.tostring();
foreach (typemembers tm in newtypemembers)
{
if (tm.fullname == fullname)
{
lstbox_members.datasource = tm.membernames;
break;
}
}
}
}
}
搜索按钮的功能就是把当前framework 2.0的所有的type,所有的type中的memberinfo封装成请求,然后调用wcf服务。服务就会根据传递过来的type和memberinfo来输出新增的方法和类。
运行效果如下:
可以看到4.0的file类增加了readlines.appendalllines方法。上面看到两个readlines是因为readlines方法由两个重载。