【WCF】自动加载 WCF Library
来源:互联网 发布:淘宝遇到职业打假敲诈 编辑:程序博客网 时间:2024/05/16 18:21
在论坛里遇到一个问题:如何做一个主程序,主程序里没有任何契约和配置文件能自动Host指定的外部的WCF Library Assembly。其实Visual Studio已经提供了类似的玩意,在你创建一个WCF Library工程之后在项目属性 -> WCF Options -> 会看到一个 "Start WCF Service Host When debugging anther project in same solution" 的选项,如果选上那么VS会自动调用 WcfSvcHost.exe 这个工具帮你托管 WCF 服务。而且VS一并提供的 WCF Test Client 给开发者十分方便的测试体验:
话说回来,通过对 Config 文件中的 serviceModel 配置节做解析完全可以自己实现,下面提供简单的实现方法:【示例代码下载】
其实我能想到上面的代码能用到地方就是自动化测试了... 另外考虑到安全的隔离每个WCF Library,应该考虑封装在 AppDomain 中。
感兴趣的童鞋,可以自己修改一下代码:使用 AppDomain.DoCallback() 封装上面的 LoadHost,需要注意的是 AppDomain 的独立性,
代理中不能有任何当前domain的数据上下文否则会抛异常。(可以使用 AppDomain.SetData / GetData 传送一些参数)
话说回来,通过对 Config 文件中的 serviceModel 配置节做解析完全可以自己实现,下面提供简单的实现方法:【示例代码下载】
(当然下面的方法还比较简陋,没有考虑什么安全配置、还有一些定义的Behavior等)
加载服务:
public static Dictionary<string, Tuple<Type, Binding, Uri>> LoadHost(Assembly assembly) { var config = ConfigurationManager.OpenExeConfiguration(assembly.Location); var svcConfig = (ServiceModelSectionGroup)config.GetSectionGroup("system.serviceModel"); var contracts = new Dictionary<string, Tuple<Type, Binding, Uri>>(); foreach (ServiceElement se in svcConfig.Services.Services) { var serviceType = assembly.GetType(se.Name); var host = new ServiceHost(serviceType); Uri baseAddress = null; foreach (BaseAddressElement ba in se.Host.BaseAddresses) { if (baseAddress == null) { baseAddress = new Uri(ba.BaseAddress); break; } } foreach (ServiceEndpointElement e in se.Endpoints) { if (!e.Binding.StartsWith("mex")) { var contract = assembly.GetType(e.Contract); var address = new Uri(baseAddress, e.Address); var binding = MapBinding(address.Scheme); host.AddServiceEndpoint(contract, binding, address); contracts.Add(e.Contract, new Tuple<Type, Binding, Uri>(contract, binding, address)); host.Open(); Console.WriteLine(se.Name + " started..."); } } } return contracts; }
通过传入的 Assembly 可以找到对应的 xxx.dll.config 文件,然后解析其中的 “system.serviceModel" 配置节。为了之后的测试,返回一个 Dictionary,
因为客户端可以通过 ChannelFactory<T>.CreateChannel(Binding, EndpointAddress) 创建连接,所以顺便把需要的数据带回来。
public static dynamic LoadClient(Type contract, Binding binding, Uri address){ var createChannel = typeof(ChannelFactory<>).MakeGenericType(contract).GetMethod("CreateChannel", new Type[] { typeof(Binding), typeof(EndpointAddress) }); dynamic channel = createChannel.Invoke(null, new object[] { binding, new EndpointAddress(address) }); return channel;}一切为了方便使用了 dynamic 类型,因为你在测试的时候一定是知道服务端的接口定义的。
运行示例:
static void Main(string[] args){ var wcfLibrary = "WcfServiceLibrary1.dll"; var assembly = Assembly.LoadFrom(wcfLibrary); var contracts = LoadHost(assembly); var testContract = contracts["WcfServiceLibrary1.IService1"]; dynamic client = LoadClient(testContract.Item1, testContract.Item2, testContract.Item3); var test1 = client.GetData(123); Console.WriteLine(test1); dynamic complexObj = assembly.CreateInstance("WcfServiceLibrary1.CompositeType"); complexObj.BoolValue = true; complexObj.StringValue = "hello"; dynamic test2 = client.GetDataUsingDataContract(complexObj); Console.WriteLine(test2.StringValue); Console.Read();}
其实我能想到上面的代码能用到地方就是自动化测试了... 另外考虑到安全的隔离每个WCF Library,应该考虑封装在 AppDomain 中。
感兴趣的童鞋,可以自己修改一下代码:使用 AppDomain.DoCallback() 封装上面的 LoadHost,需要注意的是 AppDomain 的独立性,
代理中不能有任何当前domain的数据上下文否则会抛异常。(可以使用 AppDomain.SetData / GetData 传送一些参数)
- 【WCF】自动加载 WCF Library
- 【WCF】自动加载WCF Library (IIS Host)
- Wcf
- WCF
- WCF
- WCF
- Wcf
- Wcf
- WCF
- wcf
- Wcf
- WCF
- wcf
- WCF
- WCF
- WCF
- wcf
- wcf
- switch、air-conditioner、apply for a postion、modest pension、in honor of
- virtual、as常识性检查对象、Main()、viewstate、数组
- C# 多态
- svn服务端的安装配置(本地篇)
- 浪微博布局学习——妙用TabHost
- 【WCF】自动加载 WCF Library
- c# 封装
- Android使用GPS定位及在googlemap添加标记
- 我从菜鸟起步学习linux
- Android权限大全
- Android生命周期
- App自适应draw9patch不失真背景
- c# 继承
- 百度地图API入门——(3)控件