2010-10-22 68 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