为什么动态加载程序集无法找出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 所有更新的Typeforeach (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 所有新增的TypeList<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()});}#endregionreturn 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方法由两个重载。