2015-05-13 15 views
6

Linqpad, büyük kod tabanımla çalışabileceğim tek komut dosyası ortamıdır. Benim için çalışan tek ortamın nedeni, diğer çözümlerin (ironpython vb.) Her zaman app.config dosyasından yapılandırmayı düzgün bir şekilde yükleyememesi, ancak linqpad.config'inKullanılacak linqpad yapılandırma dosyasını programsal olarak atayabilir miyim?

çalışabilmesidir. Sorun şu ki, birden çok yapılandırma dosyası ve Bir betik için bunlardan birini kullanmak istiyorum, linqpad kurulum dizinine gitmeliyim, doğru config dosyasını linqpad.config olarak yeniden adlandırıp linq'i yeniden başlatmalıyım. Çok üretken.

İçinden dosyayı ayarlamak için denedim:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config"); 

ama herhangi bir etkisi yoktu. Linqpad'de bir C# Programının Main() yönteminde kullanılacak yapılandırma dosyasını değiştirebilmem için herhangi bir yolu var mı? Kullanılacak yapılandırma dosyasını ayarlayan ve kodumun kalanını çalıştıran bir işleve çağrı yapabilirsem, bu harika olur.

+0

yapılandırma dosyası yeniden adlandırma ve LINQPad yeniden başlayarak, ayrı oluştururken düşündünüz tercih etmek yerine Klasörler, her biri istenen yapılandırma dosyasının ve LINQPad.exe dosyasının bir kopyasına sahip olur mu? –

+0

Bu, verimliliğimi gerçekten iyileştirmiyor. Belirli bir yapılandırma dosyasını kullanması gereken yeni bir sorgu oluşturmak istediğimde, aramanın en üstünde bir çağrı da dahil olmak üzere, exe + config vb. Ile yeni bir klasör oluşturmaktan çok daha hızlı olacaktır. Bu yüzden özellikle soruyorum. Programatik kurulum mümkündür. – mahonya

+2

Anladım. Şimdi mümkün değil, ancak TODO listesinde. LINQPad gelecekte buna sorgu özellikleri seçeneği ile izin verecektir. Yine de, programlı olarak asla mümkün olmayacaktır. Senaryo çalıştığında, çok geç. –

cevap

9

Örnek Linq Sorgu:

void Main() 
{ 
    var configPath = Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "app.config"); 

    // Load custom config 
    var configProxy = new ConfigurationProxy(configPath); 
    if (!configProxy.InjectToConfigurationManager()) 
    { 
     Trace.TraceError("Cannot load config from " + configPath); 
     throw new InvalidOperationException("Cannot load config " + configPath); 
    } 

    ConfigurationManager.AppSettings["LogPath"].Dump(); 
} 

sizin Linq sorgusu bu sınıfı ekleyin:

/// <summary> 
/// A custom config injector. 
/// </summary> 
public sealed class ConfigurationProxy : IInternalConfigSystem 
{ 
    /// <summary> 
    /// The custom sections 
    /// </summary> 
    private readonly Dictionary<string, IConfigurationSectionHandler> customSections; 

    /// <summary> 
    /// The configuration 
    /// </summary> 
    private Configuration config; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="ConfigurationProxy"/> class. 
    /// </summary> 
    /// <param name="fileName"> 
    /// Name of the file. 
    /// </param> 
    /// <remarks> 
    /// this is called filename but really it's the path as needed 
    /// it defaults to checking the directory you're running in. 
    /// </remarks> 
    public ConfigurationProxy(string fileName) 
    { 
     this.customSections = new Dictionary<string, IConfigurationSectionHandler>(); 

     if (!this.Load(fileName)) 
     { 
      throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "File: {0} could not be found or was not a valid configuration file.", this.config.FilePath)); 
     } 
    } 

    /// <summary> 
    /// Gets the configuration. 
    /// </summary> 
    public Configuration Configuration 
    { 
     get 
     { 
      return this.config; 
     } 
    } 

    /// <summary> 
    /// Returns the configuration object based on the specified key. 
    /// </summary> 
    /// <param name="configKey">The configuration key value.</param> 
    /// <returns> 
    /// A configuration object. 
    /// </returns> 
    public object GetSection(string configKey) 
    { 
     if (configKey == "appSettings") 
     { 
      return this.BuildAppSettings(); 
     } 

     object sect = this.config.GetSection(configKey); 

     if (this.customSections.ContainsKey(configKey) && sect != null) 
     { 
      var xml = new XmlDocument(); 

      xml.LoadXml(((ConfigurationSection)sect).SectionInformation.GetRawXml()); 

      // I have no idea what I should normally be passing through in the first 
      // two params, but I never use them in my config handlers so I opted not to 
      // worry about it and just pass through something... 
      sect = this.customSections[configKey].Create(this.config, this.config.EvaluationContext, xml.FirstChild); 
     } 

     return sect; 
    } 

    /// <summary> 
    /// The refresh config. 
    /// </summary> 
    /// <param name="sectionName"> 
    /// The section name. 
    /// </param> 
    public void RefreshConfig(string sectionName) 
    { 
     // I suppose this will work. Reload the whole file? 
     this.Load(this.config.FilePath); 
    } 

    /// <summary> 
    /// Gets a value indicating whether supports user config. 
    /// </summary> 
    public bool SupportsUserConfig 
    { 
     get 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Injects to configuration manager. 
    /// </summary> 
    /// <returns>Whether the configuration was injected</returns> 
    public bool InjectToConfigurationManager() 
    { 
     // inject self into ConfigurationManager 
     var configSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic); 
     if (configSystem != null) 
     { 
      configSystem.SetValue(null, this); 
     } 

     // lame check, but it's something 
     if (ConfigurationManager.AppSettings.Count == this.config.AppSettings.Settings.Count) 
     { 
      return true; 
     } 

     return false; 
    } 

    /// <summary> 
    /// Loads the specified file. 
    /// </summary> 
    /// <param name="file"> 
    /// The file. 
    /// </param> 
    /// <returns> 
    /// Is file loaded 
    /// </returns> 
    private bool Load(string file) 
    { 
     var map = new ExeConfigurationFileMap { ExeConfigFilename = file }; 
     this.config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 

     var xml = new XmlDocument(); 
     using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read)) 
     { 
      xml.Load(stream); 
     } 

     // var cfgSections = xml.GetElementsByTagName("configSections"); 

     // if (cfgSections.Count > 0) 
     // { 
     // foreach (XmlNode node in cfgSections[0].ChildNodes) 
     // { 
     // var type = System.Activator.CreateInstance(
     // Type.GetType(node.Attributes["type"].Value)) 
     // as IConfigurationSectionHandler; 

     // if (type == null) continue; 

     // customSections.Add(node.Attributes["name"].Value, type); 
     // } 
     // } 
     return this.config.HasFile; 
    } 

    /// <summary> 
    /// The build app settings. 
    /// </summary> 
    /// <returns> 
    /// The <see cref="NameValueCollection"/>. 
    /// </returns> 
    private NameValueCollection BuildAppSettings() 
    { 
     var coll = new NameValueCollection(); 

     foreach (var key in this.config.AppSettings.Settings.AllKeys) 
     { 
      coll.Add(key, this.config.AppSettings.Settings[key].Value); 
     } 

     return coll; 
    } 
} 
+1

İyi çalışıyor. System.pollections.Specialized System.Configuration System.Configuration.Internal ad alanları eklemeniz gerekir. Ayrıca, System.Configuration.dll dosyasına başvuru eklemeniz gerekir. – Jim

İlgili konular