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 string _dllRoot;
static ConnectionProviderRegistry()
{
_ctors = new Dictionary();
_providers = new List();
var dir = System.IO.Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
var path = System.IO.Path.Combine(dir, PROVIDER_CONFIG);
_dllRoot = System.IO.Path.GetDirectoryName(path);
XmlDocument doc = new XmlDocument();
doc.Load(path);
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;
if (!System.IO.Path.IsPathRooted(dll))
dll = System.IO.Path.Combine(_dllRoot, dll);
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)
{
System.Data.Common.DbConnectionStringBuilder builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = connectionString;
NameValueCollection values = new NameValueCollection();
foreach (string key in builder.Keys)
{
values.Add(key, builder[key].ToString());
}
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;
}
}
}