2012-09-29 205 views
0
// EF (Model) project 
class EntityBase { } // base class for all types 
class Person : EntityBase // specific implementation for type Person 

// ViewModel project 
class EditableViewModel<T> where T : EntityBase // base class for all viewmodel types 
class PersonViewModel : EditableViewModel<Person> 
class CollectionViewModel<T> where T : EditableViewModel<EntityBase> // base class that handles CRUD operation on EditableViewModel<T> collections 

// everything up to this point work. I am unable to create specific instance of CollectionViewModel<> 
class AllPersonsViewModel : CollectionViewModel<PersonViewModel> 

我該如何做到這一點?通用類型作爲泛型類型參數

+0

問題是在最後的評論,fyi。 – usr

+0

也許他沒有時間閱讀評論,但確實有時間倒計時。然後他決定刪除他的評論,發現它「不適合」。 :) – Goran

回答

1

如果你願意使用接口而不是類,你可以很容易地做協變。下面的代碼編譯得很好:

class EntityBase { } 
class Person : EntityBase {} 

interface EditableViewModel<out T> where T : EntityBase {} // Must be an interface. "out" marks T as a covariant parameter 
class PersonViewModel : EditableViewModel<Person> {} 
class CollectionViewModel<T> where T : EditableViewModel<EntityBase> { } 

class AllPersonsViewModel : CollectionViewModel<PersonViewModel> { } 
1

您得自CollectionViewModel<PersonViewModel>,但您將T限制爲EditableViewModel<EntityBase>PersonViewModelEditableViewModel<Person>,但它不是EditableViewModel<EntityBase>。這兩種類型是無關的。

他們爲什麼不相關?示例:如果B與A分配兼容,則List<B>List<A>不是分配兼容的。

如果您想了解更多關於此研究的主題,請在C#中使用co-和contravariance。

+0

所以,這意味着我可以對泛型集合類型本身做協變,但不能在類型參數上做到這一點?有沒有辦法解決這個問題,所以我可以達到以上的層次? – Goran

+0

不知道它是否可以實現,因爲我沒有這方面的經驗。無論如何,你需要引入接口,因爲只有接口可以是變體(和委託)。這會變得骯髒,每個動態的語言傢伙都會嘲笑你:「我們不需要這樣的惡臭,只是爲了關閉編譯器!」 ;-)也許這是暗示你已經離開了推薦路徑。 – usr

+0

@usr ...或者,您可以引入第二個類型參數。那麼你不需要擔心接口(儘管使用接口通常會提供更多的靈活性)。 – phoog

1

可以由此實現這一點:

class CollectionViewModel<TEntity, TViewModel> 
    where TViewModel : EditableViewModel<TEntity> 
    where TEntity : EntityBase 

class AllPersonsViewModel : CollectionViewModel<Person, PersonViewModel> 

隨着USR的回答意味着,如果你限制了類型接口而不是抽象基類,你會得到更多的靈活性;如果界面是共同的或逆變的,則這是尤其如此。