在抽象类中返回具体类型

Tom*_* B. 6 c# generics abstract-class

我们有一个抽象类BaseClass(注意泛型arg!)和一个名为me的方法.我回来了.

如果我们在具体类中使用Me,我们将得到一个返回类型对象.然后我们必须将Me的结果转换为我们最初使用的类型.

我们怎样才能实现Me返回它的实际类型?在这个例子中输入A?

public abstract class BaseClass<TIdentifier>{
 public virtual object Me{ get { return this; } }
}

public class A: BaseClass<long>
{

}

public class B: BaseClass<long>
{

}

public class controller{
   public void SomeMethod(){
       var a = new A();
       var b = new B();

       var aObject = a.Me; // this will be of type object
       var aObjectCasted = (A)aObject; // cast to original

       // How I want it
       var aConcrete = a.Me; // this returns type a
   }
}
Run Code Online (Sandbox Code Playgroud)

更新

因为有些人真的,拼命地(眨眼:-))希望了解我实际上要做的事情.

有了NHibernate,我们这样做:

var result = Session.Get<A>(idToLookUp);
Run Code Online (Sandbox Code Playgroud)

在某些情况下,由于laze加载等原因,结果不是A类型但是AProxy类型.现在如果我们想将结果转换为其他内容:我们将得到invalidcastexception,因为实际的结果类型不是但是AProxy.而且这种类型无法投放.我们只能将A类型转换为另一种类型.

此处描述了解决方法:http://sessionfactory.blogspot.be/2010/08/hacking-lazy-loaded-inheritance.html.这就是上面例子中Me属性的来源.

因此,要获得类型A的结果而不是类型AProxy,我们现在必须这样做:

var result = (A)Session.Get<A>(idToLookUp).Me;
Run Code Online (Sandbox Code Playgroud)

请注意,如果我们想要阅读并了解结果的属性,我们必须将我强制转换为类型A.

我的问题:我们可以摆脱铸造并调整Me属性,以便我们立即返回具体类型吗?

希望现在很清楚.

toa*_*akz 6

您可以在派生类上使用接口:

public interface IStrongTypedMe<T>
{
    T Me();
}
Run Code Online (Sandbox Code Playgroud)

您的派生类将变为:

public class A: BaseClass<long>, IStrongTypedMe<A>
{
    public new A Me()
    {
        return base.Me() as A;
    }
}
Run Code Online (Sandbox Code Playgroud)

A当然,这是假设您可以更改。

更新:

我现在明白这个问题(现在只有时间阅读链接的文章)。

尝试使用扩展方法为您进行转换,如下所示:

    public static TReturnType As<TReturnType,TIdentifier>(this BaseClass<TIdentifier> proxyObject)
        where TReturnType : class
    {
        return proxyObject.Me as TReturnType;
    }
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

var result = Session.Get<A>(idToLookUp).As<A,long>();
Run Code Online (Sandbox Code Playgroud)

无需更改AB要求。


Mik*_*aev 5

您可以将此属性的返回类型更改为父类的定义

public abstract class BaseClass<TIdentifier> 
{
     public virtual BaseClass<TIdentifier> Me{ get { return this; } }
}
Run Code Online (Sandbox Code Playgroud)

如果要返回完全相同的类,可以通过在泛型类型参数中添加结果类型来进行一些解决方法

public abstract class BaseClass<TIdentifier, TMe>
    where TMe : BaseClass<TIdentifier, TMe>, new()
{
    public virtual TMe Me { get { return (TMe)this; } }
}

public class A : BaseClass<long, A>
{

}
Run Code Online (Sandbox Code Playgroud)