private void EnsureLevel(ServiceConfigurationLevel level)
 {
     if (this.ConfigurationLevel != level)
     {
         throw new InvalidOperationException("Cannot modify this property");
     }
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="level">Indicates the configuration level (template, profile, or instance) to find.</param>
        /// <param name="search">Indicates whether the lowest ancestor or the highest ancestor should be found of the given type. (Highest not yet implemented).</param>
        /// <returns></returns>
        public ServiceConfiguration GetBaseConfiguration(ServiceConfigurationLevel level, ServiceConfigurationLevelSearch search = ServiceConfigurationLevelSearch.Lowest)
        {
            // TODO: implement ByLevel with search = Highest
            if (search == ServiceConfigurationLevelSearch.Highest)
            {
                throw new NotSupportedException("Only the lowest level can be found at the moment.");
            }

            ServiceConfiguration target = null;

            switch (level)
            {
            case ServiceConfigurationLevel.Instance:
                target = this.ConfigurationLevel == ServiceConfigurationLevel.Instance ? this : null;
                break;

            case ServiceConfigurationLevel.Profile:
                if (this.ConfigurationLevel == ServiceConfigurationLevel.Profile)
                {
                    target = this;
                }
                else if (this.ConfigurationLevel == ServiceConfigurationLevel.Instance)
                {
                    target = this.BaseConfiguration;
                }
                else
                {
                    target = null;
                }
                break;

            case ServiceConfigurationLevel.Template:
                target = this;
                while (target.ConfigurationLevel != ServiceConfigurationLevel.Template && target.BaseConfiguration != null)
                {
                    target = target.BaseConfiguration;
                }
                break;
            }
            return(target);
        }
        internal ServiceConfiguration Derive(ServiceConfigurationLevel newLevel, object parent)
        {
            if (this.ConfigurationLevel == ServiceConfigurationLevel.Instance)
            {
                throw new ServiceConfigurationException("Cannot derive from an instance configuration.");
            }

            ServiceConfiguration config;

            try { config = (ServiceConfiguration)Activator.CreateInstance(this.GetType()); }
            catch (MissingMethodException) { throw new MissingMethodException("Sub-types of ServiceConfiguration require a parameterless constructor."); }

            // Inherit from parent
            config.BaseConfiguration = this;
            config._isEnabled        = true;
            config._isPublic         = this._isPublic;
            config._assemblyPath     = this._assemblyPath;
            config._serviceType      = this._serviceType;
            config._serviceName      = this._serviceName;
            config._hostName         = this._hostName;
            this.Limits.CopyTo(config.Limits);

            CopyConfigurationData(this, config);

            // Merge parameters
            foreach (var param in this.Parameters)
            {
                config.Parameters[param.Key] = param.Value;
            }

            // Associate with profile
            ServiceProfile profile = parent as ServiceProfile;

            if (this.Profile != null)
            {
                if (profile == null)
                {
                    profile = this.Profile;
                }
                else if (profile != this.Profile)
                {
                    // This should never happen because it is checked by ServiceProfile.DeriveConfiguration()
                    throw new ServiceConfigurationException("Profile mismatch - internal Derive should not be called this way");
                }
            }

            if (profile != null)
            {
                config.Profile            = profile;
                config.ConfigurationLevel = ServiceConfigurationLevel.Profile;

                // Deriving from a new profile, so merge parameters (if this.Profile is not null, parameters were already merged in a previous Derive())
                if (this.Profile == null)
                {
                    foreach (var param in profile.Parameters)
                    {
                        config.Parameters[param.Key] = param.Value;
                    }
                }
            }
            else
            {
                config.ConfigurationLevel = newLevel;
            }

            // Get scheduling rules only if this one is empty
            foreach (SchedulingRule rule in this.SchedulingRules)
            {
                config.SchedulingRules.Add(rule.Clone());
            }

            // Parameter inheritance from parent service configuration
            ServiceConfiguration parentInstanceConfig = parent as ServiceConfiguration;

            if (parentInstanceConfig != null)
            {
                // Ignore parameters that are already in the config
                foreach (var param in parentInstanceConfig.Parameters)
                {
                    if (!config.Parameters.ContainsKey(param.Key))
                    {
                        config.Parameters[param.Key] = param.Value;
                    }
                }
            }

            return(config);
        }