.NET: 如何在宿主中动态加载所有的服务

今天在讲WCF的时候,谈到了一个老问题。如果我们希望宿主程序具有足够的灵活性,那么我们会用配置文件的方式来定义服务。例如下面这样


   
   xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="HelloWorldServiceLib.HelloWorldService" behaviorConfiguration="MyBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/HelloWorldService"/>
            <add baseAddress="net.tcp://localhost:8081/HelloWorld"/>
          
    
    baseAddresses>
        
     
     host>

        <endpoint address="" contract="Contracts.IHelloWorld" binding="basicHttpBinding">
      
      endpoint>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
       
       service>  
        services> <behaviors> <serviceBehaviors> <behavior name="MyBehavior"> <serviceMetadata httpGetEnabled="true"/>  
         behavior>  
          serviceBehaviors>  
           behaviors>  
            system.serviceModel>  
             configuration>

如果有这样的配置文件,那么宿主中就可以通过下面这样的代码来实现服务的托管


#region 加载一个服务宿主
            using (ServiceHost host = new ServiceHost(typeof(HelloWorldServiceLib.HelloWorldService)))
            {
                host.Open();
                Console.WriteLine("服务器已经准备好");
                Console.Read();
            }
#endregion
image 

看起来不错,不是吗?

但是,这样仍然是有一个问题,就是如果我们现在需要添加一个服务,我们当然可以修改配置文件。但此时,我们就必须修改宿主的代码,因为每一个服务都要求有一个对应的ServiceHost。

如此说来的话,我们的宿主程序就很难稳定下来了。有什么方法可以解决这个问题呢?

我们的思路是

  • 我们需要读取配置文件中,所有定义的Service节点,然后找到它们的name属性
  • 然后,我们需要根据这个name属性反射得到有关的类型

基于这样的思路,我们最后实现的完整代码如下

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.Configuration;
using System.Reflection;
using System.IO;


namespace SimpleHostUseConfiguration
{
    class Program
    {
        static void Main(string[] args)
        {



            
#region 循环加载所有的服务宿主

            //先加载当前目录下面的所有dll,然后检索里面是否有我们需要的类型
            List
  
  
   
    assemblys = 
   
   new List
   
   
    
    ();
            
    
    foreach (
    
    string file 
    
    in Directory.GetFiles(Environment.CurrentDirectory, 
    
    "*.dll")) {
                assemblys.Add(Assembly.LoadFile(file));
            }

            
    
    if (assemblys.Count > 0)
            {
                ServiceModelSectionGroup group = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).SectionGroups[
    
    "system.serviceModel"] 
    
    as ServiceModelSectionGroup;

                
    
    foreach (ServiceElement item 
    
    in group.Services.Services)
                {
                    
    
    string typeName = item.Name;
                    Type serviceType = GetTypeByName(typeName, assemblys);
                    
    
    if (serviceType != 
    
    null)
                    {
                        ServiceHost host = 
    
    new ServiceHost(serviceType);
                        host.Open();
                        Console.WriteLine(
    
    "加载服务类型成功:{0}", serviceType.FullName);
                    }
                }
            }

            Console.WriteLine(
    
    "服务器已经准备好");
            Console.Read();

    
    #endregion
        }

        
    
    /// 
        /// 这个方法从现有项目所有私有程序集中检查有关的类型
        /// 
        
    
    /// 相应的类型名称
        
    
    /// 
     
     
      
      如果找到则返回类型,否则返回NULL
     
     
        
    
    static Type GetTypeByName(
    
    string typeName,List
    
    
     
      assemblys) {
            
     
     foreach (Assembly assem 
     
     in assemblys)
            {
                Type temp = assem.GetType(typeName);
                
     
     if (temp != 
     
     null)
                    
     
     return temp;
            }

            
     
     return 
     
     null;
        }
    }
}

    
    
   
   
  
  

image

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值