1
votes

here is the end goal: get a new connection from a factory by name like so factory.CreateConnection<SqlConnection>("my db")

Here is my code so far:

type IConnectionFactory =
    abstract member CreateConnection : unit -> IDbConnection

type DefaultConnectionFactory<'t when 't : (new : unit -> 't) and 't :> IDbConnection> () =
    member this.CreateConnection () = new 't()

    interface IConnectionFactory with
        member this.CreateConnection () = this.CreateConnection() :> IDbConnection

type DefaultConnectionFactoryFactory() =
    member this.CreateConnectionFactory connectionType =
        if not (typeof<IDbConnection>.IsAssignableFrom connectionType)
        then invalidArg "connectionType" (sprintf "type %O is not assignable to IDbConnection" connectionType)

        let genericFactoryType = typedefof<DefaultConnectionFactory<_>>
        let factorytype = genericFactoryType.MakeGenericType([| connectionType |])
        Activator.CreateInstance(factorytype) :?> IConnectionFactory

type ConnectionFactory (connectionStrings : Dictionary<string, (IConnectionFactory * string)>) =
    let ConnectionStrings = connectionStrings

    member this.CreateConnection connectionStringName : 't :> IDbConnection =
        if ConnectionStrings.ContainsKey connectionStringName
        then
            let connectionFactory, connectionString = ConnectionStrings.Item connectionStringName
            let connection = connectionFactory.CreateConnection ()
            connection.ConnectionString <- connectionString
            connection :?> 't
        else invalidArg "dataSourceName" (sprintf "no data source found named %s" connectionStringName)

on this line :

let genericFactoryType = typedefof<DefaultConnectionFactory<_>>

I am getting this error: Type constraint mismatch when applying the default type 'IDbConnection' for a type inference variable. A generic construct requires that the type 'IDbConnection' have a public default constructor Consider adding further type constraints

I'm not sure how to resolve it... Any other suggestions are welcome as well

1
ConnectionFactoryFactory?? ...how meta.Daniel
I'm open to suggestions if you think there is a better way...Brad

1 Answers

3
votes

It's sort of related to this question. The problem is typedefof<DefaultConnectionFactory<_>>. The constraint on DefaultConnectionFactory requires a type that implements IDbConnection and has a default constructor. The compiler knows of no such type. So, you'll have to provide one. You could use SqlConnection, for instance:

typedefof<DefaultConnectionFactory<System.Data.SqlClient.SqlConnection>>

The effect is the same. typedefof will return the unbounded type DefaultConnectionFactory<> (in C# terms), which is impossible to express in F#.