using System; using System.Data.Common; using System.Diagnostics.CodeAnalysis; using System.Reflection; using Npgsql.Logging; namespace Npgsql; /// /// A factory to create instances of various Npgsql objects. /// [Serializable] public sealed class NpgsqlFactory : DbProviderFactory, IServiceProvider { /// /// Gets an instance of the . /// This can be used to retrieve strongly typed data objects. /// public static readonly NpgsqlFactory Instance = new(); NpgsqlFactory() {} /// /// Returns a strongly typed instance. /// public override DbCommand CreateCommand() => new NpgsqlCommand(); /// /// Returns a strongly typed instance. /// public override DbConnection CreateConnection() => new NpgsqlConnection(); /// /// Returns a strongly typed instance. /// public override DbParameter CreateParameter() => new NpgsqlParameter(); /// /// Returns a strongly typed instance. /// public override DbConnectionStringBuilder CreateConnectionStringBuilder() => new NpgsqlConnectionStringBuilder(); /// /// Returns a strongly typed instance. /// public override DbCommandBuilder CreateCommandBuilder() => new NpgsqlCommandBuilder(); /// /// Returns a strongly typed instance. /// public override DbDataAdapter CreateDataAdapter() => new NpgsqlDataAdapter(); #if !NETSTANDARD2_0 /// /// Specifies whether the specific supports the class. /// public override bool CanCreateDataAdapter => true; /// /// Specifies whether the specific supports the class. /// public override bool CanCreateCommandBuilder => true; #endif #if NET6_0_OR_GREATER /// public override bool CanCreateBatch => true; /// public override DbBatch CreateBatch() => new NpgsqlBatch(); /// public override DbBatchCommand CreateBatchCommand() => new NpgsqlBatchCommand(); #endif #region IServiceProvider Members /// /// Gets the service object of the specified type. /// /// An object that specifies the type of service object to get. /// A service object of type serviceType, or null if there is no service object of type serviceType. [RequiresUnreferencedCode("Legacy EF5 method, not trimming-safe.")] public object? GetService(Type serviceType) { if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); // In legacy Entity Framework, this is the entry point for obtaining Npgsql's // implementation of DbProviderServices. We use reflection for all types to // avoid any dependencies on EF stuff in this project. EF6 (and of course EF Core) do not use this method. if (serviceType.FullName != "System.Data.Common.DbProviderServices") return null; // User has requested a legacy EF DbProviderServices implementation. Check our cache first. if (_legacyEntityFrameworkServices != null) return _legacyEntityFrameworkServices; // First time, attempt to find the EntityFramework5.Npgsql assembly and load the type via reflection var assemblyName = typeof(NpgsqlFactory).GetTypeInfo().Assembly.GetName(); assemblyName.Name = "EntityFramework5.Npgsql"; Assembly npgsqlEfAssembly; try { npgsqlEfAssembly = Assembly.Load(new AssemblyName(assemblyName.FullName)); } catch { return null; } Type? npgsqlServicesType; if ((npgsqlServicesType = npgsqlEfAssembly.GetType("Npgsql.NpgsqlServices")) == null || npgsqlServicesType.GetProperty("Instance") == null) throw new Exception("EntityFramework5.Npgsql assembly does not seem to contain the correct type!"); return _legacyEntityFrameworkServices = npgsqlServicesType .GetProperty("Instance", BindingFlags.Public | BindingFlags.Static)! .GetMethod!.Invoke(null, new object[0]); } static object? _legacyEntityFrameworkServices; #endregion }