Home
Help
Register
Log in

Search

 
   Active Threads  

You are here: Home > LLBLGen Pro > LLBLGen Pro Runtime Framework> ApplicationConfiguration class is very unflexible
 

Pages: 1
LLBLGen Pro Runtime Framework
ApplicationConfiguration class is very unflexible
Page:1/1 

  Print all messages in this thread  
Poster Message
worldspawn
User



Location:
Melbourne, Australia
Joined on:
26-Aug-2006 06:56:13
Posted:
321 posts
# Posted on: 09-Mar-2007 00:52:25.  
The ApplicationConfiguration class is annoying. It reads settings using AppSettingsReader so the settings MUST come from the currently executing executables configuration file. So for a visual studio add-in the settings must be added to devenv.exe.config!! It then goes on to look for driver definitions in a folder relative to the executing executables startup path.

Basically meaning unless the ApplicationConfiguration class is instantiated from an application launched from the LLBLGen Pro installation folder it will fail.

Code:

private void LoadDatabaseDriverDefinitions()
{
     string text1 = Path.Combine(Application.StartupPath, this._databaseDriversRootFolder);
     string[] textArray1 = Directory.GetDirectories(text1);
...
}


It needs a static method or something it can create an instance of itself with a provided configuration reader as well as a provided path to look for driver definitions.

In the meantime i'm just going to call the CliRefresher tool as a separate process. Dissapointed
--
Sam Critchley
Dotnet 3.5 - SQL Server 2005 - LLBLGen Pro 3.0
 
Top
worldspawn
User



Location:
Melbourne, Australia
Joined on:
26-Aug-2006 06:56:13
Posted:
321 posts
# Posted on: 09-Mar-2007 04:14:57.  
I'm now trying to figure out how to generate for a single entity and i see that Generator.Start requires an instance of ApplicationConfiguration... *sigh*.

I suppose I'm going to have to use the CommandLineGenerator from the SDK... Dissapointed


--
Sam Critchley
Dotnet 3.5 - SQL Server 2005 - LLBLGen Pro 3.0
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
38081 posts
# Posted on: 09-Mar-2007 11:29:11.  
worldspawn wrote:
The ApplicationConfiguration class is annoying. It reads settings using AppSettingsReader so the settings MUST come from the currently executing executables configuration file. So for a visual studio add-in the settings must be added to devenv.exe.config!! It then goes on to look for driver definitions in a folder relative to the executing executables startup path.

Yup, but it's not that annoying. The purpose is that it's used with an llblgen pro install, as the usage of that code needs a license.

I understand what you're doing but the code at the moment isn't designed to be used as a vs.net add-in.

Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Alex Davidson
User



Location:
Bristol, UK
Joined on:
18-Sep-2006 17:51:08
Posted:
21 posts
# Posted on: 13-Mar-2007 12:53:30.  
This is a problem I needed to solve some time ago.

http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7785

Eventually, I solved it by using some rather dodgy reflection techniques to poke around inside the ConfigurationManager and hook the required configuration sections.

Code:

public static class ReflectionUtils
    {
        public static void SetAppDomainBaseDirectory(string dir)
        {
            (new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert();
            try
            {
                AppDomainSetup ads = typeof (AppDomain).InvokeMember("FusionStore", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty, null, AppDomain.CurrentDomain, new object[] {}) as AppDomainSetup;
                ads.ApplicationBase = dir;
            }
            finally
            {
                CodeAccessPermission.RevertAssert();
            }
        }
    }
    
    /// <summary>
    /// A substitute for ConfigurationManager's backing object. Acts an an adapter to
    /// allow ConfigurationManager to use a Configuration object.
    /// </summary>
    public class ReplacementConfigSystem : IInternalConfigSystem
    {
        private Configuration _base;
        private IInternalConfigSystem _original;
        private string _appPath;

        /// <summary>
        /// Create an object that wraps a Configuration object and can plug into
        /// ConfigurationManager.
        /// </summary>
        /// <param name="appPath">Full path to the application's executable</param>
        public ReplacementConfigSystem(string appPath)
        {
            _appPath = appPath;
            _base = ConfigurationManager.OpenExeConfiguration(appPath);
        }
        
        #region Install/Uninstall hook
        /// <summary>
        /// Substitute the current app's configuration data for this one.
        /// Uses reflection to replace the ConfigurationManager's settings and change
        /// Application.StartupPath. Currently only replaces AppSettings.
        /// </summary>
        public void Install()
        {
            if (_original == null)
            {
                string appDir = Path.GetDirectoryName(_appPath);
                (new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert();
                try
                {
                    BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
                    Type configManType = typeof(ConfigurationManager);
                    Type appObjType = typeof(Application);

                    // Force config system initialisation to complete.
                    configManType.InvokeMember("EnsureConfigurationSystem", flags | BindingFlags.InvokeMethod, null, null, new object[] { });

                    // Get the object upon which init locking is performed and make the swap.
                    object lockObj = configManType.InvokeMember("s_initLock", flags | BindingFlags.GetField, null, null, new object[] { });
                    lock (lockObj)
                    {
                        _original = configManType.InvokeMember("s_configSystem", flags | BindingFlags.GetField, null, null, new object[] { }) as IInternalConfigSystem;
                        if (_original == null)
                        {
                            throw new OperationCanceledException("Configuration initialisation was incomplete. Unable to install hook.");
                        }
                        else
                        {
                            try
                            {
                                // Install the hook.
                                configManType.InvokeMember("s_configSystem", flags | BindingFlags.SetField, null, null, new object[] { this });
                                appObjType.InvokeMember("startupPath", flags | BindingFlags.SetField, null, null, new object[] { appDir });
                            }
                            catch
                            {
                                // Attempt to roll back.
                                Uninstall();
                                throw;
                            }
                        }
                    }
                }
                catch
                {
                    _original = null;
                    throw;
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                }
            }
            else
            {
                throw new Exception("Hook already installed. Cannot reinstall.");
            }
        }

        /// <summary>
        /// Restores ConfigurationManager and Application.StartupPath.
        /// </summary>
        public void Uninstall()
        {
            if (_original != null)
            {
                (new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert();
                try
                {
                    BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
                    Type configManType = typeof(ConfigurationManager);
                    Type appObjType = typeof(Application);
                    object lockObj = configManType.InvokeMember("s_initLock", flags | BindingFlags.GetField, null, null, new object[] { });
                    lock (lockObj)
                    {
                        configManType.InvokeMember("s_configSystem", flags | BindingFlags.SetField, null, null, new object[] { _original });
                        appObjType.InvokeMember("startupPath", flags | BindingFlags.SetField, null, null, new object[] { null });
                        _original = null;
                    }
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                }
            }
            else
            {
                throw new Exception("Hook not installed. Cannot uninstall.");
            }
        }
        #endregion

        #region IInternalConfigSystem Members
        /// <summary>
        /// Return the requested Section from the Configuration object.
        /// Sections are handled differently by ConfigurationManager, so
        /// this method reconstructs the Section in an appropriate manner.
        /// </summary>
        /// <param name="configKey">Key name</param>
        /// <returns></returns>
        public object GetSection(string configKey)
        {
            if (_base != null)
            {
                NameValueCollection properties = new NameValueCollection();
                ConfigurationSection section = _base.GetSection(configKey);
                if (section is AppSettingsSection)
                {
                    foreach (KeyValueConfigurationElement element in (section as AppSettingsSection).Settings)
                    {
                        properties.Add(element.Key, element.Value);
                    }
                    return properties;
                }
            }
            return _original.GetSection(configKey);
        }

        public void RefreshConfig(string sectionName)
        {
            _original.RefreshConfig(sectionName);
        }

        public bool SupportsUserConfig
        {
            get
            {
                return true;
            }
        }
        #endregion
    }


Quite nasty and it may need revising if the internals of ConfigurationManager ever change. Also, it only supports the <appSettings> section at present.

Use it like so:

Code:

string llblgenExe = /* full path to LLBLGen executable */;
ReplacementConfigSystem llblgenConfig = new ReplacementConfigSystem(llblgenExe);
llblgenConfig.Install();
// do LLBLGen-y stuff that uses ApplicationConfiguration.
llblgenConfig.Uninstall();



  Top
Aurelien
Support Team



Location:
France
Joined on:
28-Jun-2006 16:32:08
Posted:
162 posts
# Posted on: 13-Mar-2007 14:49:17.  
thanks for your contribution !
Aricie  Top
worldspawn
User



Location:
Melbourne, Australia
Joined on:
26-Aug-2006 06:56:13
Posted:
321 posts
# Posted on: 19-Apr-2007 07:51:15.  
Thanks Alex, I'll give that a try Regular Smiley

--
Sam Critchley
Dotnet 3.5 - SQL Server 2005 - LLBLGen Pro 3.0
 
Top
Pages: 1  


Powered by HnD ©2002-2007 Solutions Design
HnD uses LLBLGen Pro

Version: 2.1.12172008 Final.