using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.Reflection; using System.Collections.Specialized; namespace OSGeo.MapGuide.MaestroAPI { public class ConnectionProviderEntry { public string Name { get; private set; } public string Description { get; private set; } internal ConnectionProviderEntry(string name, string desc) { this.Name = name; this.Description = desc; } } /// /// The supports dynamic creation of objects given a provider name /// and a connection string, which specifies the initialization parameters of the connection. The connection providers are defined in an XML /// file called ConnectionProviders.xml which contains all the registered providers. Each provider has the following properties: /// /// 1. The name of the provider /// 2. The assembly containing the implementation /// 3. The name of this implementation. /// /// The implementation is expected to have a non-public constructor which takes a single parameter, /// a containing the initialization parameters parsed from the given connection /// string. /// public sealed class ConnectionProviderRegistry { const string PROVIDER_CONFIG = "ConnectionProviders.xml"; static Dictionary _ctors; static List _providers; static ConnectionProviderRegistry() { _ctors = new Dictionary(); _providers = new List(); XmlDocument doc = new XmlDocument(); doc.Load(PROVIDER_CONFIG); XmlNodeList providers = doc.SelectNodes("//ConnectionProviderRegistry/ConnectionProvider"); foreach (XmlNode prov in providers) { string name = prov["Name"].InnerText.ToUpper(); string desc = prov["Description"].InnerText; string dll = prov["Assembly"].InnerText; string type = prov["Type"].InnerText; Assembly asm = Assembly.LoadFrom(dll); Type t = asm.GetType(type); _ctors[name] = t; _providers.Add(new ConnectionProviderEntry(name, desc)); } } private static NameValueCollection ParseConnectionString(string connectionString) { NameValueCollection values = new NameValueCollection(); string[] tokens = connectionString.Split(';'); foreach (string tok in tokens) { string[] nameValue = tok.Split('='); if (nameValue.Length == 2) { values.Add(nameValue[0], nameValue[1]); } } return values; } /// /// Gets a list of registered provider names. The returned names are in upper-case. /// /// public static ConnectionProviderEntry[] GetProviders() { return _providers.ToArray(); } /// /// Creates an initialized object given the provider name and connection string /// /// /// /// public static ServerConnectionI CreateConnection(string provider, string connectionString) { string name = provider.ToUpper(); if (!_ctors.ContainsKey(name)) throw new ArgumentException("Provider not registered: " + provider); Type t = _ctors[name]; NameValueCollection initParams = ParseConnectionString(connectionString); BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance; ServerConnectionI conn = (ServerConnectionI)t.InvokeMember(null, flags, null, null, new object[] { initParams }); return conn; } } }