简体   繁体   English

C#泛型类的隐式转换

[英]Implicit conversion en C# generic classes

I have an application that is structured as an service layer wich uses a repository layer for persistence. 我有一个结构化为服务层的应用程序,它使用存储库层来实现持久性。 I'm trying to create a generic controller class to reuse shared behavior but I'm having trouble trying to set the generic parameters. 我正在尝试创建一个通用控制器类来重用共享行为,但我在设置泛型参数时遇到了麻烦。 The following code: 以下代码:

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>
{ }

fails at compilation with 编译失败

The type ConsoleApplication.IPersonService cannot be used as type parameter Y in the generic type or method ConsoleApplication.BaseController<X,Y> . ConsoleApplication.IPersonService类型不能用作泛型类型或方法ConsoleApplication.BaseController<X,Y>中的类型参数Y There is no implicit reference conversion from ConsoleApplication.IPersonService to ConsoleApplication.IService<ConsoleApplication.Person,ConsoleApplication.IRepository<ConsoleApplication.Person>> ConsoleApplication.IPersonServiceConsoleApplication.IService<ConsoleApplication.Person,ConsoleApplication.IRepository<ConsoleApplication.Person>>没有隐式引用转换。

this works 这很有效

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

but I lose the custom repository 但我失去了自定义存储库

There is a way to make the compiler realize IPersonRepository is an IRepository<Person> ? 有一种方法可以使编译器实现IPersonRepository是一个IRepository<Person>

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>
{ } 

To address your comment: 解决你的评论:

IPersonService can extend the base service class to add custom facilities, like FindPersonsUnderAge(). IPersonService可以扩展基本服务类以添加自定义工具,如FindPersonsUnderAge()。 For this it requires a custom repository. 为此,它需要一个自定义存储库。 Actually LINQ avoids a lot of custom repository code, but sometimes they are required. 实际上LINQ避免了很多自定义存储库代码,但有时它们是必需的。

Couldn't IPersonService do that without requiring the repository type to be a type parameter? 如果不要求存储库类型是类型参数,IPersonService能不能这样做吗? For example: 例如:

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
{ }

Thanks to sll for pointing me in the right direction 感谢sll指出我正确的方向

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

does the trick 诀窍

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM