2012-02-01 54 views
1

這裏是最終目標泛型類型定義:得到一個工廠的名字,像這樣factory.CreateConnection<SqlConnection>("my db")F#獲取型與約束

這裏是我到目前爲止的代碼一個新的連接:

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) 

在這行:應用默認型「的IDbConnection」的類型推斷變量時 類型約束不匹配:

let genericFactoryType = typedefof<DefaultConnectionFactory<_>> 

我得到這個錯誤。一個通用的結構要求的類型「的IDbConnection」有一個公共的默認構造函數考慮進一步增加類型約束

我不知道如何解決它...任何其他建議,歡迎以及

+1

'ConnectionFactoryFactory'? ...如何元。 – Daniel 2012-02-01 20:47:31

+0

如果你認爲有更好的方法,我願意接受這些建議...... – Brad 2012-02-01 20:49:27

回答

3

這有點與this question有關。問題是typedefof<DefaultConnectionFactory<_>>DefaultConnectionFactory上的約束需要一個類型,它實現了IDbConnection並且具有默認構造函數。編譯器知道沒有這種類型。所以,你必須提供一個。您可以使用SqlConnection,例如:

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

效果是一樣的。 typedefof將返回無限類型DefaultConnectionFactory<>(使用C#術語),這在F#中是無法表達的。

+0

是啊....我發現它能夠工作,但它看起來很糟糕,就像我缺少一些簡單的東西。我一直認爲必須有一種方法來獲得泛型類型定義而不提供類型。感謝您的參考......我沒有看到,當我搜索。 – Brad 2012-02-01 20:56:52

+0

F#不提供指定無限類型的方法。如果約束很平凡,並且通常會解析爲'obj',則可以使用通配符(就像您一樣)。 – Daniel 2012-02-01 21:01:39