基类方法可以返回派生类的类型吗? [英] Can a Base Class Method return the type of the derived class?

查看:134
本文介绍了基类方法可以返回派生类的类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于我读过的其他帖子,似乎这可能是不可能的,但我想我会发布我想要做的事情,看看是否有人知道解决方案。

Based on the other posts I have read, it seems that this may not be possible, but I thought I would post what I am trying to do and see if anyone knows of a solution.

我正在尝试向Telerik Open Access域模型生成的类添加Clone()方法。没问题。我能够弄清楚如何将基类添加到生成的实体模型中,以便我可以通过它们的基类来识别这些类。 (所有实体都从基类继承

I am trying to add a "Clone()" method to classes generated from a Telerik Open Access domain model. No problem. I was able to figure out how to add a base class to the generated entity models so that I could identify those classes by their base class. (All entities inherit from a base class)

我希望所有这些实体模型类能够克隆自己。我也找到了解决方案。 (深度克隆对象

I want ALL these entity model classes to be able to Clone themselves. I have found a solution for that as well. (Deep Cloning Objects)

现在我有一个基类,我想为每个派生自该基类的类添加一个Clone()函数。所以...看起来基类是放置它的自然场所......对吗?

Now I have a base class and I want to add a Clone() function to every class that derives from that base class. So ... it seems that the base class is the natural place to put it ... right?

public abstract class DBEntityBase
{
    /// <summary>
    ///     Gets a COPY of the instance in it's current state
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    protected T Clone<T>()
    {
        return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(this));
    }
}

我添加受保护的通用克隆() 方法因为在基类级别我们不知道我们正在克隆的类型。 Clone()方法需要由实体模型本身实现,以便提供克隆的特定类型。

I add the protected generic Clone() method because at the base class level we don't know the Type we are cloning. The Clone() method needs to be implemented by the entity model itself in order to provide the specific type being cloned.

public partial class DeliverableEntity
{
    public new DeliverableEntity Clone()
    {
        return this.Clone<DeliverableEntity>();
    }
}

这很好,但不是 保证 派生类将公开公开Clone()方法,因此我将抽象Clone()方法添加到 的基础要求 派生类来实现公共Clone()方法。

This works fine, but does not guarantee that derived classes will publicly expose a Clone() method, so I added an abstract Clone() method to the base which will require the derived class to implement a public Clone() method.

public abstract class DarkRoomDBEntityBase
{
    /// <summary>
    ///     Gets a COPY of the instance in it's current state
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    protected T Clone<T>()
    {
        return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(this));
    }

    /// <summary>
    ///     Gets a deep COPY of the entity instance
    /// </summary>
    /// <returns></returns>
    public abstract DBEntityBase Clone();
}

我给它一个基类本身的返回类型;每个实现必须返回一个遵循DBEntityBase的值,当然,所有派生类都会这样做。由于Clone()方法返回一个派生类本身的类型,然后...似乎有意义这可行。

I give it a return type of the base class itself; every implementation MUST return a value which adheres to the DBEntityBase, which of course, all derived classes do. Since the Clone() method is returning a type of the derived class itself then ... it seems to make sense that this would work.

DeliverableEntity originalEntity = new DeliverableEntity();
DeliverableEntity clonedEntity   = originalEntity.Clone();

然而,在构建时,我收到错误..

When building, however, I get the error ..


'DeliverableEntity'不实现继承的抽象成员
'DBEntityBase.Clone()'

'DeliverableEntity' does not implement inherited abstract member 'DBEntityBase.Clone()'

大概是由于返回类型。

Presumably due to the return type.

我知道我可能只是将Clone()方法放在一个单独的实用程序类中,而不是直接在每个实体模型中实现它...这会让我绕过我的问题(可能会保存很多实现代码),但我仍然想知道为什么这不起作用。好像应该有办法做到这一点。

I know that I COULD just put the Clone() method in a separate utility class and not implement it directly in each entity model ... that would get me around my problem (and probably save a lot of implementation code), but I am still left wondering why this won't work. It seems like there should be a way to do this.

更新

为了回应@Luann的第一个回复(谢谢)我将更改改为覆盖......

In response to @Luann's first reply (thank you) I made the change to "override" ...

public partial class DeliverableEntity
{
    public override DeliverableEntity Clone()
    {
        return this.Clone<DeliverableEntity>();
    }
}

现在收到以下错误......

and am now receiving the following error ...


返回类型必须是'DBEntityBase'才能匹配被覆盖的成员
'DBEntityBase.Clone()'

return type must be 'DBEntityBase' to match overridden member 'DBEntityBase.Clone()'

解决方案

感谢Flynn1179我能够再次前进。我想我会花一点时间来记录我在这里做了什么以供将来参考..

Thanks to Flynn1179 I was able to move forward again. I thought I would take a moment to document what I did here for future reference ..

而不是为ORM中的每个实体模型创建一个部分类,实现一个抽象方法,我按照建议创建了一个扩展方法。

Instead of creating a partial class for each entity model in the ORM, implementing an abstract method, I created a single extension method as suggested.

namespace DAL
{
    public partial class DeliverableEntity : DBEntityBase
    {
         // ... Code generated from ORM 
    }

    public partial class DeliverableItemEntity : DBEntityBase
    {
         // ... Code generated from ORM 
    }

    public partial class DeliverableItemAttrEntity : DBEntityBase
    {
         // ... Code generated from ORM 
    }
}

namespace DAL
{
    public static class EntityExtensionMethods
    {
        public static T Clone<T>(this T entity) where T: DBEntityBase
        {
            return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(entity));
        }
    }
}

有些事需要注意.. 。

Some things to note ...


  • 将此类放在与实体模型相同的命名空间中。如果它位于不同的命名空间中,那么您需要添加该命名空间才能访问该方法。

  • 我将泛型类型的约束定义为仅包含继承该类型的所有类。 DBEntityBase 类。由于我将所有实体模型类派生自此基类,我知道所有这些类都将公开此方法,但是任何不从此类派生的类都不具备此功能。

  • 扩展方法和包含它的类必须是静态

  • Put this class in the same Namespace as the entity models. If it's in a different namespace then you will need to add that namespace in order to have access to the method.
  • I defined the constraint on the generic type to only and all classes which inherit the DBEntityBase class. Since I made all my entity model classes derive from this base class I know that all of them will will expose this method but also that any class which does NOT derive from this class will NOT have this capability.
  • The extension method and the class that contains it must be static

现在很酷的部分是所有实体都可以访问该函数...

Now the cool part is that ALL the Entities have access to the function ...

    // Create the original instances of the entities    
    DeliverableEntity origDeliverable       = new DeliverableEntity();
    DeliverableItemEntity origItem          = new DeliverableItemEntity();
    DeliverableItemAttrEntity origItemAttr  = new DeliverableItemAttrEntity();

    // now here's the magic 

    DeliverableEntity cloneDeliverable      = origDeliverable.Clone();
    DeliverableItemEntity cloneItem         = origItem.Clone();
    DeliverableItemAttrEntity cloneItemAttr = origItemAttr.Clone();

我喜欢这个解决方案,因为它具有基类的简单性,其中实现在单个中定义location(而我正在考虑在每个派生类中单独实现一个抽象方法)加上因为它与DBEntityBase类相关联并且在同一名称空间中,它成为基类定义的契约的一部分,这意味着我可以依赖每当我有一个派生自DBEntityBase的类时它就可用。

I love this solution as it's has the simplicity of a base class where the implementation is defined in a single location (whereas I was looking at implementing an abstract method individually in each derived class) plus since it's associated with the DBEntityBase class and in the same namespace, it becomes part of the "contract' defined by the base class which means I can count on it being available whenever I have a class derived from DBEntityBase.

推荐答案

按受欢迎的要求..

尝试扩展方法:

public T Clone<T>(this T obj) where T : DBEntityBase
{
  return /* insert code that creates clone here */
}

我必须诚实,我不认为这会起作用,因为我预计C#将无法准确确定它的扩展名。显然它确实如此!

I have to be honest, I didn't think this would work, as I expected C# would be unable to determine exactly what it's an extension of. Apparently however, it does!

这篇关于基类方法可以返回派生类的类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆