public IList<T> SelectByNo<T>(string no) where T : User {}
public IList<User> SelectByNo(string no),我的意思是最后调用的时候可以这样:Ilist<Profile> profiles = SelectByNo(no);Ilist<Profile> is Ilist<User>.如何实现呀?
@Scott Lewis: 还是没太明白你的意图,有没有完整的用例?
@Ninja_Lu: 意思是SelectByNo(no)既能返回Ilist<user>,也能返回Ilist<profile>
@Scott Lewis: 如果必须是“既能返回IList<User>又能返回IList<Profile>”,那么你只能通过范型约束来做到这一点:
public IList<T> SelectByNo<T>(string no) where T : User {} //usage: IList<User> users = Bar.SelectByNo<User>("some no"); IList<Profile> profiles = Bar.SelectByNo<Profile>("some no");
如没有没指定范型约束就想让SelectByNo“智能”的返回IList<User>或IList<Profile>这样的具类是不可以的,最多也只能返回IList<User>这样级别的结构(即便是方法内返回了IList<Profile>)。
其实如果这样的需求成立,那么好的设计应该是设计两个接口,SelectUserByNo和SelectProfileByNo而不是通过范型来做类型的筛选,因为你一旦已经抽象出了User和Profile的继承结构,那么就不应该针对User和Profile来具体的处理,否则就违背了抽象设计的原则。
@Ninja_Lu: “好的设计应该是设计两个接口,SelectUserByNo和SelectProfileByNo而不是通过范型来做类型的筛选,因为你一旦已经抽象出了User和Profile的继承结构,那么就不应该针对User和Profile来具体的处理”什么意思,设计两个接口不就是针对user和profile具体处理的么?下面代码的SelectUserByUserNo联合查询的user和profile,你觉得我是分开写两个方法好还是写一个方法好?
/// <summary>
/// 通过编号获得用户实例
/// </summary>
/// <param name="no">编号</param>
/// <returns></returns>
public IList<T> SelectByNo<T>(string no) where T : User
{
SecUtility.CheckParameter(ref no, true, true, true, 0, "no");
return SqlMapper.QueryForList<T>("SelectUserByUserNo", no);
}
@Scott Lewis:
就我来看,SelectByNo方法应该只返回IList<User>结构,因为你已经做了抽象的处理:Profile < User,那么接下来的业务就是在User结构内,例如有User.DoSomeThing()方法,Profile里覆写这个方法,这才是继承结构的正确使用方式。如果,你既要对User结构进行具体的操作,又要对Profile结构进行具体的操作,那么这里的继承结构就是有问题的,也就是说逻辑上是没有层级关系的两个类。(这是从设计的角度看)
现在的问题是,你的需求是SelectByNo要既可以返回IList<User>又可以返回IList<Profile>,本质上就是在对继承层次的不同具类做分别的操作了,所以我前面说了,SelectByNo应该只返回IList<User>,统一的进行抽象编程。
那么我再猜测一下,User在数据库里是一张表,Profile是和User表共享主键(或有外键约束)的表。如果是这样的话,其实是一种包含的关系,即User包含0-1的Profile,不应该是继承的关系。如果这个猜测是错的话,就忽略这段话吧。:-P
@Ninja_Lu: 这个方法其实是写在Dao层的
@Ninja_Lu:确实是包含的关系
@Scott Lewis: 那也只能这样了,语言级别只能够用下面的方法了:
public IList<T> SelectByNo<T>(string no) where T : User {}
//usage:
IList<User> users = Bar.SelectByNo<User>("some no");
IList<Profile> profiles = Bar.SelectByNo<Profile>("some no");
或者更大胆的方式(想想都可怕):
public IList<dynamic> SelectByNo(string no) {}
设计级别改不了的话就无能为力了……
@Ninja_Lu: 是可以在user里加一条public profile profile{get;set;}的,但这样要用到级联查询或者自己去写个方法查询,我就想用一次性获得所有属性,才有了这样的需求。谢谢你了,泛型我是刚刚接触,以前都没有使用过。
public class Profile :User
public IList<User> SelectByNo(string no) {
......
}
public IList<User> SelectByNo(string no),我的意思是最后调用的时候可以这样:Ilist<Profile> profiles = SelectByNo(no);Ilist<Profile> is Ilist<User>.如何实现呀?