示例#1
0
        void OnOutcomeReported(ServiceOutcome outcome, bool save = true)
        {
            OutcomeProperty.SetValue(this, outcome);

            if (save)
            {
                this.Save();
            }

            if (this.OutcomeReported != null)
            {
                OutcomeReported(this, EventArgs.Empty);
            }

            // Service is done, so unsubscribe to the engine's events
            if (_commChannel != null)
            {
                if (_commChannel.State == CommunicationState.Opened)
                {
                    _commChannel.Engine.Unsubscribe();
                }
                else
                {
                    _commChannel.Abort();
                }
            }

            /*
             * // Remove event handlers from child services
             * foreach (ServiceInstance child in _childServices.Keys)
             * {
             *  StateChanged -= _childStateHandler;
             *  OutcomeReported -= _childOutcomeHandler;
             * }
             */
        }
        /*=========================*/
        #endregion

        #region Setup
        /*=========================*/

        public void Initialize()
        {
            // EXCEPTION:
            if (State != ServiceState.Uninitialized)
            {
                throw new InvalidOperationException("Service can only be initialized once per lifetime.");
            }

            // Change state to initializing - will invoke save, thus getting a new instanceID
            State = ServiceState.Initializing;

            // Get the service URL based on the instance ID6
            if (this.ServiceUrl == null)
            {
                string baseUrl = AppSettings.Get(typeof(Service), "BaseListeningUrl");
                ServiceUrlProperty.SetValue(this, String.Format(baseUrl, this.InstanceID));
            }

            // Check whether the service is accessible via WCF. If it is, skip the Appdomain loading
            try
            {
                OpenChannelAndSubscribe();
            }
            catch
            {
                // Communcation test failed, meaning we need to set up the service (assumisng it's down)
                _commChannel.Abort();

                AppDomainSetup setup       = new AppDomainSetup();
                string         assemblyDir = AppSettings.Get(typeof(Service), "AssemblyDirectory");
                setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
                setup.PrivateBinPath  = Path.IsPathRooted(assemblyDir) ?
                                        assemblyDir :
                                        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyDir);

                // Load the AppDomain in a different thread
                Action loadAppDomain = new Action(delegate()
                {
                    try
                    {
                        _appDomain = AppDomain.CreateDomain(this.ToString(), null, setup);
                    }
                    catch (Exception ex)
                    {
                        // Report failure
                        State = ServiceState.Ended;
                        OnOutcomeReported(ServiceOutcome.Failure);

                        // EXCEPTION:
                        throw new Exception(String.Format("Failed to create a new AppDomain for the service. Service name: {0}.", Configuration.Name), ex);
                    }
                });

                // Once the app domain loading create the instance
                loadAppDomain.BeginInvoke(new AsyncCallback(delegate(IAsyncResult result)
                {
                    try
                    {
                        _appDomain.CreateInstance(typeof(ServiceStart).Assembly.FullName, typeof(ServiceStart).FullName,
                                                  false, BindingFlags.CreateInstance, null, new object[] { new ServiceInstanceInfo(this) }, null, null, null);
                    }
                    catch (Exception ex)
                    {
                        // Unload app domain because we can't use it anymore
                        AppDomain.Unload(_appDomain);

                        // Report failure
                        State = ServiceState.Ended;
                        OnOutcomeReported(ServiceOutcome.Failure);

                        // EXCEPTION:
                        throw new Exception(String.Format("Failed to initialize the service. Service name: {0}.", Configuration.Name), ex);
                    }

                    // Try to open it again now that the service is running
                    OpenChannelAndSubscribe();
                }
                                                            ), null);
            }
        }