And*_*rew 5 c# generics return-type linq-to-sql
我遇到了方法的返回类型的问题.
该方法返回一个linq对象,该对象目前返回类型tblAppointment.此方法如下所示:
public tblAppointment GetAppointment(int id)
{
var singleAppointment = (from a in dc.tblAppointments
where a.appID == id
select a).SingleOrDefault();
return singleAppointment;
}
Run Code Online (Sandbox Code Playgroud)
问题是tblAppointment是抽象的并且有许多继承它的子类型.当我尝试它返回一个对象,它的类型是"appointmentTypeA"并调用.GetType()方法,它给了我正确的子类型,但是当我试图访问属性只允许我以访问父属性.如果我拿走对象并将它投射到子类型的新对象然后它工作,让我访问我需要的一切,但它似乎很乱.
var viewSingleAppointment = appointmentRepos.GetAppointment(appointmentId);
Debug.Write(viewSingleAppointment.GetType()); //returns type i want
if (viewSingleAppointment is tblSingleBirthAppointment)
{
tblSingleBirthAppointment myApp = (tblSingleBirthAppointment)viewSingleAppointment; //need to do this to access TypeA properties for some reason
}
Run Code Online (Sandbox Code Playgroud)
编辑:我有这个工作,但我需要使用select语句每次约会(约20),并将其转换为相应的类型和retreive属性和林不知道如何重构这个,因为它会在几个页面中使用我们正在做.
好吧,如果你正在使用C#4,你可以使用动态类型...但是如果你想坚持静态类型,我怀疑你能做的最好就是提供预期类型作为泛型类型参数,并获得方法为你执行演员:
public T GetAppointment<T>(int id) where T : tblAppointment
{
var singleAppointment = (from a in dc.tblAppointments
where a.appID == id
select a).SingleOrDefault();
return (T) singleAppointment;
}
Run Code Online (Sandbox Code Playgroud)
称之为:
SpecificAppointment app = GetAppointment<SpecificAppointment>(10);
Run Code Online (Sandbox Code Playgroud)
或使用隐式输入:
var app = GetAppointment<SpecificAppointment>(10);
Run Code Online (Sandbox Code Playgroud)
如果转换失败,它将在执行时抛出异常.
这假定调用者知道约会类型(尽管他们可以指定tblAppointment
他们是否不这样做).在编译时不知道适当的约会类型,很难看出静态类型如何能为你带来更多好处,真的......
你正在解决错误的问题.如果你有一个超类A
,与子类B
,C
等等,所有具有类似的功能,要做到以下几点:
做A
一个接口B
,C
等实现.通过提供的接口工作的代码B
或C
实例A
.如果您可以定义一组适用于所有类型的通用操作,那么这就是您需要做的.
如果您无法定义一组通用操作,例如,您的代码类似于:
A foo = GetA();
if(foo is B) {
B bFoo = (B) foo;
// Do something with foo as a B
} else if(foo is C) {
C cFoo = (C) foo;
// Do something with foo as a C
} ...
Run Code Online (Sandbox Code Playgroud)
甚至这个(基本上是相同的,只是使用额外的信息来模拟系统已经为你提供的类型):
A foo = GetA();
MyEnum enumeratedValue = foo.GetEnumeratedValue();
switch(enumeratedValue) {
case MyEnum.B:
B bFoo = (B) foo;
// Do something with foo as a B
break;
case MyEnum.C:
C cFoo = (C) foo;
// Do something with foo as a C
break;
}
Run Code Online (Sandbox Code Playgroud)
然后你真正想要做的事情是:
A foo = GetA();
foo.DoSomething();
Run Code Online (Sandbox Code Playgroud)
每个子类都将实现switch
语句的相应分支.这在几个方面实际上更好:
switch
/ case
块,因此您不会冒任何意外忘记添加相应的新增子类的风险.如果将方法保留在子类之外,则会出现编译时错误.B
C
case
DoSomething()
A
编辑:回复您的评论:
如果您的DoSomething()
例程需要在一个Form
或其他GUI元素上运行,只需将该元素传递给该方法即可.例如:
public class B : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a B object!";
}
}
public class C : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a C object!";
}
}
// elsewhere, in a method of MyForm:
A foo = GetA();
foo.DoSomething(this);
Run Code Online (Sandbox Code Playgroud)
或者,更好的想法可能是将您的B
和C
类转换为自定义控件,因为它们似乎封装了显示逻辑.
归档时间: |
|
查看次数: |
8080 次 |
最近记录: |