如何投射到Wrapper容器?

时间:2017-08-09 08:43:58

标签: c# linq oop inheritance casting

以下是来自DLL的PaginaScheda的定义:

public class Pagina : BrObject
{
    public const int Home = 1;

    public Pagina();

    public string Titolo { get; set; }
    public string IDStatoPubblicazione { get; set; }
    public string Descrizione { get; set; }
    public string DescBreve { get; set; }
    public Allegati Immagini { get; }

    ... many others properties
}

public class Scheda : BrObject
{
    public Scheda();

    public string Latitudine { get; set; }
    public string SottoTitolo { get; set; }
    public string Titolo { get; set; }
    public PeriodiValidita PeriodiValidita { get; }
    public Allegati Immagini { get; }
    public Allegati Documenti { get; }
    public string Descrizione { get; set; }

    ... many others properties
}

现在,我想做一个wrapper课程,所以我可以把它们投到我的课堂上,只获得我需要的“一些常用参数”:

public class WrapperObject : BrObject
{
    public string Titolo { get; set; }
    public string Descrizione { get; set; }
    public Allegati Immagini { get; set; }

    public WrapperObject()
    {

    }
}

但是当我尝试这样做时:

IList<Pagina> ListatoPagine = GetPagine();
IList<WrapperObject> list = new List<WrapperObject>();

...

list = ListatoPagine.Cast<WrapperObject>().ToList();

失败:无法将“BrLayer.Pagina”类型的对象强制转换为“WrapperObject”。

我对OOP和C#有点生锈......

4 个答案:

答案 0 :(得分:2)

您没有向程序提供有关如何将Pagina的一个实例转换为包装类的任何信息。

这可以通过例如通过这个:

list = ListatoPagine.Select(x => new WrapperObject { 
    Titolo  = x.Titolo,
    Descrizione  = x.Descrizione,
    Immagini  = x.Immagini
}).ToList();

另一种方法是在包装类中引入一个拷贝构造函数:

public class WrapperObject : BrObject
{
    public string Titolo { get; set; }
    public string Descrizione { get; set; }
    public Allegati Immagini { get; set; }

    public WrapperObject(BrObject o)
    {
        this.Titolo  = o.Titolo;
        this.Descrizione = o.Descrizione;
        this.Immagini = o.Immagini;
    }
}

然后可以这样调用:

list = ListatoPagine.Select(x => new WrapperClass(x)).ToList();

编辑:由于基类上不存在属性,您需要两个复制构造函数,每个导出类型一个:

public WrapperObject(Pagina o)
{
    this.Titolo  = o.Titolo;
    this.Descrizione = o.Descrizione;
    this.Immagini = o.Immagini;
}

对于另一个班级。无论如何,你最好定义一个所有类都实现的接口,并定义所有的common-properties。这样,您可以基于实现该公共接口的existiong实例创建WrapperClass的新实例。

答案 1 :(得分:2)

继承是一种方式。

我们假设您有一个班级Oak,然后是一个继承自Tree的班级List<Oak>

您可以将List<Tree>投射到Oak,因为所有Tree都是List<Tree>

但是你不能List<Oak>进入Tree,因为并非所有Oak都是{{1}}。

你在这里遇到了完全相同的问题。

@HimBromBeere provides a solution解决您的问题。

答案 2 :(得分:2)

您目前的情况

public class Pagina : BrObject
public class Scheda : BrObject
public class WrapperObject : BrObject

PaginaSchedaWrapperObject是三个类,都来自BrObject。你可以考虑他们&#34;兄弟姐妹&#34;。

这三个兄弟之间没有定义任何关系,除了他们有相同的基类。这意味着允许以下演员表:

向上投射
这可以隐式完成,并且始终是正确的。

  • PaginaBrObject
  • SchedaBrObject
  • WrapperObjectBrObject

向下投射
这需要显式转换,仅在原始对象来自派生类(例如Pagina)但是被转换为其基类(BrObject)时才有效。从本质上讲,只有在你已经投降后才能抛弃(因此反转/撤消演员阵容)。

  • BrObjectPagina
  • BrObjectScheda
  • BrObjectWrapperObject

PaginaWrapperObject之间没有有效的演员。你不能从一个兄弟姐妹转变为另一个兄弟姐妹。
如果您使用Pagina对象,将其转换为BrObject,然后将其转换为Scheda对象,编译器将不会抱怨。它相信你知道你在做什么。当你写一个明确的演员表时,你基本上凌驾于编译器的天生意义上来指出你的逻辑缺陷。
但是,运行此代码时会收到例外情况,因为Pagina不是Scheda,反之亦然

没有有效的方法来强制横向(兄弟姐妹之间)。即使你设法欺骗编译器,你仍然会在运行时遇到异常。

这三个属性在PaginaSchedaWrapperObject中定义:

public string Titolo { get; set; }
public string Descrizione { get; set; }
public Allegati Immagini { get; set; }

它们在任何地方都具有相同的名称(和类型)。但是,这是巧合。这些字段之间没有定义任何关系,它们恰好被称为相同。

作为一个简单示例,请考虑myCountry.NamemyUser.Name。这是两个独立的名称属性,与彼此无关。

我建议的解决方案

我怀疑您需要以下OOP方法:

  • WrapperObject派生自BrObject
  • PaginaScheda均来自WrapperObject

在此更正版本中,您始终可以隐式地将任何Pagina对象投射到WrapperObject。这同样适用于Scheda 请注意,从PaginaScheda仍然没有有效的演员(反之亦然),但您的问题并不表示需要这样做。

实现这个:

  1. 更正继承:

    public class Pagina : WrapperObject 
    public class Scheda : WrapperObject 
    public class WrapperObject : BrObject
    
  2. 将这三个属性保留在WrapperObject中,但删除来自PaginaScheda的相同属性。

  3. 您的演员现在应该按预期工作(在您的示例中):

    myWrapperObjectList = myPaginaList.Cast<WrapperObject>().ToList();
    
  4. 现在这是一个有效的演员,因为Pagina继承自WrapperObject

    修改

    我的同事告诉我,我很困惑&#34; up&#34; &#34; down&#34;在谈论铸造时。这引起了我们团队的争论,不是每个人都以同样的方式看待它 我的方式可能与SO上的大多数人看待它的方式不同。

    但是,它与您面临的问题并不完全相关。 &#34;向上&#34; &#34; down&#34;是抽象的概念,你可以使用你喜欢的任何一个。

    我将我的版本保留在这里,以便在我撰写未来评论时保持一致。

答案 3 :(得分:1)

WrapperObject既不是Pagina也不是Scheda,因此您无法将其转换为WrapperObject。这是他们的兄弟姐妹(在同一级别)。

听起来像你不需要BrObject,而是BrObject(父母)的集合 - 假设sht.range("30:30").api.Insert(InsertShiftDirection.xlShiftToRight) 正确设计了正确的“共享”属性。