Skip to content

Commit

Permalink
Hook up ProviderRepository to FactoryTools
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Willey committed Mar 10, 2016
1 parent e12586a commit ace54f7
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 84 deletions.
65 changes: 34 additions & 31 deletions DatabaseSchemaReader/Utilities/DbProviderFactoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ namespace DatabaseSchemaReader.Utilities
///declared at app.config or machine.config. Basically extracted from
///http://sandrinodimattia.net/dbproviderfactoryrepository-managing-dbproviderfactories-in-code/
/// </summary>
public static class DbProviderFactoryRepository
public class DbProviderFactoryRepository
{
/// <summary>
///The table containing all the data.
/// </summary>
private static DataTable _dbProviderFactoryTable;
private DataTable _dbProviderFactoryTable;

/// <summary>
///Initialize the repository.
/// </summary>
static DbProviderFactoryRepository()
public DbProviderFactoryRepository()
{
LoadDbProviderFactories();
}
Expand All @@ -32,7 +32,7 @@ static DbProviderFactoryRepository()
///Gets all providers.
/// </summary>
/// <returns></returns>
public static IEnumerable<DbProviderFactoryDescription> GetAllDescriptions()
public IEnumerable<DbProviderFactoryDescription> GetAllDescriptions()
{
return _dbProviderFactoryTable.Rows.Cast<DataRow>().Select(o => new DbProviderFactoryDescription(o));
}
Expand All @@ -42,7 +42,7 @@ public static IEnumerable<DbProviderFactoryDescription> GetAllDescriptions()
/// </summary>
/// <param name="invariant"></param>
/// <returns></returns>
public static DbProviderFactoryDescription GetDescriptionByInvariant(string invariant)
public DbProviderFactoryDescription GetDescriptionByInvariant(string invariant)
{
var row =
_dbProviderFactoryTable.Rows.Cast<DataRow>()
Expand All @@ -55,7 +55,7 @@ public static DbProviderFactoryDescription GetDescriptionByInvariant(string inva
/// </summary>
/// <param name="description">The description.</param>
/// <returns></returns>
public static DbProviderFactory GetFactory(DbProviderFactoryDescription description)
public DbProviderFactory GetFactory(DbProviderFactoryDescription description)
{
var providerType = //AssemblyHelper.LoadTypeFrom(description.AssemblyQualifiedName);
Type.GetType(description.AssemblyQualifiedName);
Expand All @@ -81,7 +81,7 @@ public static DbProviderFactory GetFactory(DbProviderFactoryDescription descript
/// </summary>
/// <param name="invariant">The invariant.</param>
/// <returns></returns>
public static DbProviderFactory GetFactory(string invariant)
public DbProviderFactory GetFactory(string invariant)
{
if (string.IsNullOrEmpty(invariant))
{
Expand All @@ -98,7 +98,7 @@ public static DbProviderFactory GetFactory(string invariant)
/// <param name="path">The path.</param>
/// <exception cref="System.ArgumentNullException"></exception>
/// <exception cref="System.ArgumentException">$Path does not {path} exist.</exception>
public static void LoadExternalDbProviderAssemblies(string path)
public void LoadExternalDbProviderAssemblies(string path)
{
LoadExternalDbProviderAssemblies(path, true);
}
Expand All @@ -110,7 +110,7 @@ public static void LoadExternalDbProviderAssemblies(string path)
/// <param name="includeSubfolders">if set to <c>true</c> [include subfolders].</param>
/// <exception cref="System.ArgumentNullException"></exception>
/// <exception cref="System.ArgumentException">$Path does not {path} exist.</exception>
public static void LoadExternalDbProviderAssemblies(string path, bool includeSubfolders)
public void LoadExternalDbProviderAssemblies(string path, bool includeSubfolders)
{
if (string.IsNullOrEmpty(path))
{
Expand Down Expand Up @@ -180,30 +180,11 @@ public static void LoadExternalDbProviderAssemblies(string path, bool includeSub
}
}

/// <summary>
/// Gets the loadable types.
/// </summary>
/// <param name="assembly">The assembly.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">assembly</exception>
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
if (assembly == null) throw new ArgumentNullException("assembly");
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}

/// <summary>
///Adds the specified provider.
/// </summary>
/// <param name="provider">The provider.</param>
public static void Add(DbProviderFactoryDescription provider)
public void Add(DbProviderFactoryDescription provider)
{
Delete(provider);
_dbProviderFactoryTable.Rows.Add(provider.Name, provider.Description, provider.InvariantName, provider.AssemblyQualifiedName);
Expand All @@ -213,7 +194,7 @@ public static void Add(DbProviderFactoryDescription provider)
///Deletes the specified provider if present.
/// </summary>
/// <param name="provider">The provider.</param>
private static void Delete(DbProviderFactoryDescription provider)
private void Delete(DbProviderFactoryDescription provider)
{
var row =
_dbProviderFactoryTable.Rows.Cast<DataRow>()
Expand All @@ -227,9 +208,31 @@ private static void Delete(DbProviderFactoryDescription provider)
/// <summary>
///Opens the table.
/// </summary>
private static void LoadDbProviderFactories()
private void LoadDbProviderFactories()
{
_dbProviderFactoryTable = DbProviderFactories.GetFactoryClasses();
}
}

internal static class AssemblyExtensions
{
/// <summary>
/// Gets the loadable types.
/// </summary>
/// <param name="assembly">The assembly.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">assembly</exception>
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
if (assembly == null) throw new ArgumentNullException("assembly");
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}
}
}
97 changes: 49 additions & 48 deletions DatabaseSchemaReader/Utilities/FactoryTools.cs
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
using System;
using System.Data;
using System.Data.Common;

namespace DatabaseSchemaReader.Utilities
{
/// <summary>
/// Tools to help with DbProviderFactory
/// </summary>
public static class FactoryTools
{
private static DbProviderFactory _manualProviderFactory;

/// <summary>
/// Finds the factory.
/// </summary>
/// <param name="providerName">Name of the provider.</param>
/// <returns></returns>
public static DbProviderFactory GetFactory(string providerName)
{
//a simple static manual override.
if (_manualProviderFactory != null) return _manualProviderFactory;
return DbProviderFactories.GetFactory(providerName);
}


/// <summary>
/// Adds an existing factory. Call this before creating the DatabaseReader or SchemaReader. Use with care!
/// </summary>
/// <param name="factory">The factory.</param>
/// <exception cref="System.ArgumentNullException">schemaReader</exception>
public static void AddFactory(DbProviderFactory factory)
{
if (factory == null) throw new ArgumentNullException("factory");
_manualProviderFactory = factory;
}


/// <summary>
/// List of all the valid Providers. Use the ProviderInvariantName to fill ProviderName property
/// </summary>
/// <returns></returns>
public static DataTable Providers()
{
return DbProviderFactories.GetFactoryClasses();
}
}
}
using System;
using System.Data;
using System.Data.Common;

namespace DatabaseSchemaReader.Utilities
{
/// <summary>
/// Tools to help with DbProviderFactory
/// </summary>
public static class FactoryTools
{
/// <summary>
/// Finds the factory. You can override with <see cref="P:SingleProviderFactory"/> (simple) or <see cref="P:ProviderRespository"/>
/// </summary>
/// <param name="providerName">Name of the provider.</param>
/// <returns></returns>
public static DbProviderFactory GetFactory(string providerName)
{
//a simple static manual override.
if (SingleProviderFactory != null) return SingleProviderFactory;
if (ProviderRepository != null) return ProviderRepository.GetFactory(providerName);
return DbProviderFactories.GetFactory(providerName);
}


/// <summary>
/// Adds an existing factory. Call this before creating the DatabaseReader or SchemaReader. Use with care!
/// </summary>
public static DbProviderFactory SingleProviderFactory { get; set; }

/// <summary>
/// Gets or sets a provider repository.
/// </summary>
/// <value>
/// The provider repository.
/// </value>
public static DbProviderFactoryRepository ProviderRepository { get; set; }


/// <summary>
/// List of all the valid Providers. Use the ProviderInvariantName to fill ProviderName property
/// </summary>
/// <returns></returns>
public static DataTable Providers()
{
return DbProviderFactories.GetFactoryClasses();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System;
using System.Data.Common;
using System.Data.SqlClient;
using DatabaseSchemaReader;
using DatabaseSchemaReader.Utilities;
#if !NUNIT
using Microsoft.VisualStudio.TestTools.UnitTesting;
#else
using NUnit.Framework;
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
#endif

namespace DatabaseSchemaReaderTest.Utilities
Expand All @@ -26,22 +30,72 @@ public void TestRepository()
};

// Initialize the repository.
DbProviderFactoryRepository.Add(manualDescription);
var repo = new DbProviderFactoryRepository();
repo.Add(manualDescription);

var descs = DbProviderFactoryRepository.GetAllDescriptions();
var descs = repo.GetAllDescriptions();
foreach (var description in descs)
{
//get the description individually
var desc = DbProviderFactoryRepository.GetDescriptionByInvariant(description.InvariantName);
var desc = repo.GetDescriptionByInvariant(description.InvariantName);
Assert.AreEqual(description.AssemblyQualifiedName, desc.AssemblyQualifiedName);

//get a factory
var factory = DbProviderFactoryRepository.GetFactory(desc);
var factory = repo.GetFactory(desc);
//may be null if not accessible
}

//look in the current directory
DbProviderFactoryRepository.LoadExternalDbProviderAssemblies(Environment.CurrentDirectory);
repo.LoadExternalDbProviderAssemblies(Environment.CurrentDirectory);
}

[TestMethod]
public void FactoryToolsTest()
{
const string providername = "System.Data.SqlClient";

//this is normally used
var provider = FactoryTools.GetFactory(providername);
Assert.AreEqual("System.Data.SqlClient.SqlClientFactory", provider.GetType().FullName, "No override, returns SqlClient");

//override with a repository
FactoryTools.ProviderRepository = new DbProviderFactoryRepository();
var manualDescription = new DbProviderFactoryDescription
{
Description = ".NET Framework Data Provider for SuperDuperDatabase",
InvariantName = "SuperDuperDatabase",
Name = "SuperDuperDatabase Data Provider",
AssemblyQualifiedName = typeof(SuperDuperProviderFactory).AssemblyQualifiedName,
};
FactoryTools.ProviderRepository.Add(manualDescription);

provider = FactoryTools.GetFactory(providername);
Assert.AreEqual("System.Data.SqlClient.SqlClientFactory", provider.GetType().FullName, "Overridden, but returns underlying SqlClient");
provider = FactoryTools.GetFactory("SuperDuperDatabase");
Assert.AreEqual(typeof(SuperDuperProviderFactory), provider.GetType(), "Overridden, returns manually added provider");

//override with a single provider
FactoryTools.SingleProviderFactory = SqlClientFactory.Instance;
provider = FactoryTools.GetFactory("Xxxx");
Assert.AreEqual("System.Data.SqlClient.SqlClientFactory", provider.GetType().FullName, "Overridden, always returns SqlClient");

var dr = new DatabaseReader(ConnectionStrings.Northwind, "Xxxxx");
var tables = dr.TableList();

Assert.IsTrue(tables.Count > 0, "We called the reader with a bogus provider type, but we got the overridden type");
}

[TestCleanup]
public void CleanUp()
{
//reset the overrides
FactoryTools.ProviderRepository = null;
FactoryTools.SingleProviderFactory = null;
}

public class SuperDuperProviderFactory : DbProviderFactory
{
public static SuperDuperProviderFactory Instance = new SuperDuperProviderFactory();
}
}
}

0 comments on commit ace54f7

Please sign in to comment.