2012-03-07 171 views
3

我有一個應用程序被構造爲一個服務層,它使用存儲庫層進行持久化。 我想創建一個泛型控制器類來重用共享行爲,但我在嘗試設置泛型參數時遇到了問題。以下代碼:隱式轉換en C#泛型類

public class BusinessEntity 
{ } 

public class Person : BusinessEntity 
{ } 

public interface IRepository<T> where T : BusinessEntity 
{ } 

public interface IService<T, R> 
    where T : BusinessEntity 
    where R : IRepository<T> 
{ } 

public partial interface IPersonRepository : IRepository<Person> 
{ } 

public interface IPersonService : IService<Person, IPersonRepository> 
{ } 

public abstract class BaseController<X, Y> 
    where X : BusinessEntity 
    where Y : IService<X, IRepository<X>> 
{ } 

public class PersonController : BaseController<Person, IPersonService> 
{ } 

在編譯失敗並

類型ConsoleApplication.IPersonService不能在通用類型或方法ConsoleApplication.BaseController<X,Y>被用作類型參數Y。有一個從ConsoleApplication.IPersonServiceConsoleApplication.IService<ConsoleApplication.Person,ConsoleApplication.IRepository<ConsoleApplication.Person>>

這個作品

public interface IPersonService : IService<Person, IRepository<Person>> 

沒有隱式引用轉換,但我失去了自定義庫

有一種方法,使編譯器實現IPersonRepositoryIRepository<Person>

+1

權,這是因爲'IRepository 其中X:Person'是不一樣的'IRepository '默認情況下,默認情況下這種通用類型沒有差異。你正在使用哪個版本的.NET Framework? – sll 2012-03-07 19:51:54

+0

如果我有能力,我會給你一個「打破編譯器」徽章。從我花了5分鐘的時間努力使其工作,我的直覺結論是,編譯器不夠聰明,無法做你想做的事情。 – PlayDeezGames 2012-03-07 20:03:21

+0

我正在使用.Net 4.我沒有想過差異,我認爲它值得一試。 – 2012-03-08 21:55:23

回答

4
public class BusinessEntity 
{ } 

public class Person : BusinessEntity 
{ } 

public interface IRepository<T> where T : BusinessEntity 
{ } 

public interface IService<T, R> 
    where T : BusinessEntity 
    where R : IRepository<T> 
{ } 

public partial interface IPersonRepository : IRepository<Person> 
{ } 

public interface IPersonService : IService<Person, IPersonRepository> 
{ } 

public abstract class BaseController<X, Y, Z> 
    where X : BusinessEntity 
    where Y : IService<X, Z> 
    where Z : IRepository<X> 
{ } 

public class PersonController : BaseController<Person, IPersonService, IPersonRepository> 
{ } 

爲了解決您的評論:

IPersonService可擴展基礎服務類添加自定義的設施,如FindPersonsUnderAge()。爲此,它需要一個自定義存儲庫。實際上,LINQ避免了很多自定義存儲庫代碼,但有時它們是必需的。

如果不要求存儲庫類型是類型參數,IPersonService不能做到這一點嗎?例如:

public interface IService<T> where T : BusinessEntity { } 

public interface IPersonService : IService<Person> 
{ 
    IEnumerable<Person> FindPersonsByAge(double minAge, double maxAge); 
} 

public class Service<T, R> : IService<T> 
    where T : BusinessEntity 
    where R : IRepository<T> 
{ } 

public class PersonService : Service<Person, IPersonRepository>, IPersonService 
{ } 
+0

我不完全喜歡UI開發人員必須知道存儲庫的事實,但這是一個可以接受的折中方案。 – 2012-03-08 21:59:49

+0

@JamesGordon在這種情況下,我會爲'interface IPersonService:IService '拍攝,因此服務的使用者不需要知道服務如何保存其數據 - 甚至不需要依賴於IRepository < >'。 PersonService的哪些方法需要人員存儲庫的類型參數? – phoog 2012-03-12 19:54:13

+0

IPersonService可以擴展基本服務類以添加自定義設施,如FindPersonsUnderAge()。爲此,它需要一個自定義存儲庫。實際上,LINQ避免了很多自定義存儲庫代碼,但有時它們是必需的。 – 2012-03-13 12:06:03

0

感謝SLL指着我在正確的方向

public interface IService<T, out R> 
    where T : BusinessEntity 
    where R : IRepository<T> 
{ } 

的伎倆