代码改变世界

AutoWCFService心跳动态加载服务

2012-06-27 10:25  leo.wl2020  阅读(389)  评论(0编辑  收藏  举报
    public partial class AutoHostingService : ServiceBase
    {
        #region fields

        private static ServiceDispacher _dispacher;

        #endregion

        #region .ctor

        public AutoHostingService()
        {
            InitializeComponent();
            InitializeWindsor();
        }

        #endregion

        #region Methods

        protected override void OnStart(string[] args)
        {
            _dispacher = new ServiceDispacher();
            _dispacher.Start();
        }

        protected override void OnStop()
        {
            if (_dispacher != null)
            {
                _dispacher.Close();
            }
        }

        
        public void OnStart()
        {
            this.OnStart(null);
        }

        protected virtual void InitializeWindsor()
        {
            if (ServiceProvider.Provider == null)
            {
                IWindsorContainer container = 
          new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
                ServiceProvider.Initialize(new WinsorServiceProvider(container));
            }
        }

        #endregion

 

Main:

        static void Main(String[] args)
        {
            if (args.Length > 0)
            {
                new AutoHostingService().OnStart();

                Console.WriteLine("Finished");
                Console.Read();
            }
            else
            {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
            { 
                new AutoHostingService() 
            };
                ServiceBase.Run(ServicesToRun);
            }
        }

 

        protected override void OnStart(string[] args)
        {
            _dispacher = new ServiceDispacher();
            _dispacher.Start();
        }

        protected override void OnStop()
        {
            if (_dispacher != null)
            {
                _dispacher.Close();
            }
        }

 

ServiceDispacher:

        public void Start()
        {
            var list = ServiceLoader.Load();

            foreach (Type t in list.Keys)
            {
                var serviceHost = ServiceHostHandler.CreateServiceHost(t, list[t]);

                if (serviceHost != null)
                {
                    serviceHosts.Add(serviceHost);
                }
            }

            serviceHosts.ForEach(serviceHost =>
            {
                serviceHost.Open();

                _log.InfoFormat("LISTENING:{0}", serviceHost.BaseAddresses[0].ToString());
            });
        }

        public void Close()
        {
            serviceHosts.ForEach(serviceHost =>
            {
                ServiceHostHandler.CloseServiceHost(serviceHost);
                _log.InfoFormat("CLOSE SERVICE:{0}", serviceHost.BaseAddresses[0].ToString());
            });
        }

 

        public static ServiceHost CreateServiceHost(Type typeInstance, List<Type> interfaces)
        {
            if (interfaces == null || interfaces.Count == 0)
            {
                return null;
            }

            //set {BaseAddress} {Domain} {ServiceName}
            string baseAddress = ConfigSettings.BaseAddress;
            string domainName = GetDomainName(typeInstance.FullName);

            string url = Path.Combine(baseAddress, domainName)   "/"   typeInstance.Name;

            //Add ServiceHost
            ServiceHost host = new ServiceHostEx(typeInstance, new Uri(url));

            //Add ServiceBehavior
            var serviceMetaBehavior = host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>();
            if (serviceMetaBehavior == null)
            {
                host.Description.Behaviors.Add(new ServiceMetadataBehavior()
                {
                    HttpGetEnabled = true
                });
            }

            //Add ServiceDebugBehavior
            var serviceDebugBehavior = host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceDebugBehavior>();

            serviceDebugBehavior.IncludeExceptionDetailInFaults = true;

            // Add ServiceThrottlingBehavior
            ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior();
            throttlingBehavior.MaxConcurrentCalls = 500;
            throttlingBehavior.MaxConcurrentInstances = Int32.MaxValue;
            throttlingBehavior.MaxConcurrentSessions = 500;
            host.Description.Behaviors.Add(throttlingBehavior);

            // Open Metadata
            host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            //BasicHttp
            BasicHttpBinding binding = new BasicHttpBinding("Default");

            // Add ServiceEndpoint
            interfaces.ForEach(implementedContract =>
            {
                host.AddServiceEndpoint(implementedContract, binding, "");
            });

            return host;
        }

        #endregion

        #region CloseServiceHost

        public static void CloseServiceHost(ServiceHost serviceHost)
        {
            if (serviceHost != null && serviceHost.State != CommunicationState.Closed)
            {
                _log.InfoFormat("CLOSE :{0}", serviceHost.BaseAddresses[0].ToString());

                serviceHost.Close();
                serviceHost = null;
            }
        }

        #endregion

        #region Helper

        private static string GetDomainName(string fullName)
        {
            if (string.IsNullOrEmpty(fullName))
            {
                return string.Empty;
            }

            string[] strArray = fullName.Split('.');

            if (strArray.Length > 2)
            {
                return strArray[strArray.Length - 2];
            }

            return string.Empty;
        }

        #endregion

 

        public static IDictionary<Type, List<Type>> Load()
        {
            IDictionary<Type, List<Type>> serviceImplements = new Dictionary<Type, List<Type>>();

            // Get All Types
            List<Type> types = GetTypes();

            // Get All ServiceContract
            List<Type> serviceContracts = GetServiceContracts(types);

            // Get Servers Imp
            serviceImplements = GetServiceContractsImplements(serviceContracts, types);

            return serviceImplements;
        }


        private static List<Type> GetTypes()
        {
            Dictionary<string, Type> types = new Dictionary<string, Type>();

            string[] files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, ConfigSettings.AssemblyFilter);

            files.ToList().ForEach(file =>
            {
                try
                {
                    Assembly.LoadFrom(file).GetTypes().ToList().ForEach(type =>
                    {
                        if (!types.ContainsKey(type.FullName))
                        {
                            types.Add(type.FullName, type);
                        }
                    });
                }
                catch
                {
                    throw new ApplicationException(file);
                }
            });

            return types.Values.ToList();
        }

       
        private static IDictionary<Type, List<Type>> GetServiceContractsImplements(IList<Type> serviceContracts, List<Type> types)
        {
            IDictionary<Type, List<Type>> serviceImplements = new Dictionary<Type, List<Type>>();

            if (serviceContracts.Count == 0)
            {
                return serviceImplements;
            }

            types.ForEach(type =>
            {
                serviceContracts.ToList().ForEach(contract =>
                {
                    if (type.IsInterface)
                    {
                        return;
                    }

                    if (!contract.IsAssignableFrom(type))
                    {
                        return;
                    }

                    if (serviceImplements.ContainsKey(type))
                    {
                        var list = serviceImplements[type];
                        if (!list.Contains(contract))
                        {
                            list.Add(contract);
                        }
                    }
                    else
                    {
                        serviceImplements.Add(type, new List<Type> { contract });
                    }


                });
            });

            return serviceImplements;
        }

        
        private static List<Type> GetServiceContracts(List<Type> types)
        {
            List<Type> serviceContracts = new List<Type>();

            if (types == null)
            {
                return serviceContracts;
            }

            types.ForEach(type =>
            {
                if (type.FullName.StartsWith(ConfigSettings.ContractAssemblyPrefix))
                {
                    var attrs = type.GetCustomAttributes(typeof(ServiceContractAttribute), false);

                    if (attrs.Length > 0)
                    {
                        serviceContracts.Add(type);
                    }
                }
            });

            return serviceContracts;
        }

       

       public class ServiceHostEx : ServiceHost    

       {        

           public ServiceHostEx(Type type)             : base(type)         {}


           public ServiceHostEx(Type serviceType, params Uri[] baseAddresses)             : base(serviceType, baseAddresses)         {         }


           protected override void InitializeRuntime()         {            

                     base.InitializeRuntime();


                    foreach (ChannelDispatcher dispatcher in this.ChannelDispatchers) {                 dispatcher.ErrorHandlers.Add(new FaultHandler());             }        

            }    

      }   


       public class FaultHandler : IErrorHandler     {        

        #region fields


        private static log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);


        #endregion


       

        public bool HandleError(Exception exception){            

                try{               

                while (exception != null){

                     Console.Error.WriteLine(exception.StackTrace);

                    _log.Error(exception);                    

                     exception = exception.InnerException;                

                }            

             }catch{}

            return true;         }


        public void ProvideFault(Exception error, System.ServiceModel.Channels.MessageVersion version, ref System.ServiceModel.Channels.Message fault)         {            

                 if (fault == null)

                 {

                    FaultException<FaultException> fe = new FaultException<FaultException>(new FaultException(error.Message));

                  MessageFault mf = fe.CreateMessageFault();

                    fault = System.ServiceModel.Channels.Message.CreateMessage(version, mf, fe.Action);             }         }

      }