2010-10-22 67 views
0

我對泛型方法的約束有問題。這裏是所有類代碼:泛型類型問題的一般方法

namespace Sdk.BusinessObjects 
{ 
    public interface IBusinessObject 
    { 
    } 
} 

namespace Sdk.BusinessObjects 
{ 
    [DataContract] 
    public class AccountDetails : IBusinessObject 
    { 
     [DataMember] 
     public virtual Guid AccountId { get; set; } 

    // More properties... 
    } 
} 

namespace Sdk.BusinessLogic 
{ 
    public interface IManager<T> where T : IBusinessObject 
    { 
     T Add(T businessObject); 
     void Delete(T businessObject); 
     IList<T> ListAll(); 
    } 
} 

namespace Sdk.BusinessLogic 
{ 
    public interface IAccountManager : IManager<AccountDetails> 
    { 
     void ChangeAccountState(Guid accountId, string state); 
    } 
} 

namespace Sdk.BusinessLogic 
{ 
    public interface IManagerFactory 
    { 
     T Create<T>() where T : IManager<IBusinessObject>; 
    } 

    public class ManagerFactory : IManagerFactory 
    { 
     public T Create<T>() where T : IManager<IBusinessObject> 
     { 
      // resolve with Unity and return 
     } 
    } 
} 

所以,我對所有的業務對象(如AccountDetails)主IBusinessObject接口和iManager中作爲通用管理接口的業務對象。我想要爲這些經理製造工廠並加以限制。當我嘗試這樣在單元測試:

IManagerFactory factory = new ManagerFactory(); 
factory.Create<IAccountManager>(); 

我得到錯誤: 類型「Sdk.BusinessLogic.IAccountManager」不能用作泛型類型或方法「Sdk.BusinessLogic類型參數「T」。 IManagerFactory.Create()」。沒有從'Sdk.BusinessLogic.IAccountManager'到'Sdk.BusinessLogic.IManager'的隱式引用轉換。

這怎麼辦?

回答

1

基本上你的問題是,IManager<T>是不變的,必須像你有API的價值觀和價值觀進入它。因此,一個IAccountManager不是一個IManager<IBusinessObject>,因爲否則的話你可以寫:

IAccountManager m1 = new SomeImplementation(); 
IManager<IBusinessObject> m2 = m1; 
m2.Add(new SomeArbitraryBusinessObject()); 

客戶經理只是爲了管理賬戶,不是任何業務對象。

一種選擇是使用兩個泛型類型參數,而不是一個ManagerFactory.Create

public TManager Create<TManager,TObjectType>() 
    where TManager : IManager<TObjectType> 
    where TObjectType : IBusinessObject 
+0

是的,你是對的,但我不喜歡有兩個泛型參數實現,因爲沒有有意義的嘗試用IBusinessObject的其他一些實現來解析IAccountManager。我認爲最好的解決方案是放棄泛型類型參數的約束,並在實現中強制執行它:T創建(); – IvanQ 2010-10-22 10:21:07

+0

@IvanQ:這取決於你是否想要編譯時安全,基本上。另一種選擇是創建一個非泛型的'IManager'界面,其中'IManager '來源於。 – 2010-10-22 10:36:50

+0

是的,我在考慮非泛型IManager,但它會是空的,所以我現在拒絕了這個想法。 – IvanQ 2010-10-22 10:47:21