如何更改此代码以允许抽象类或接口在相同的自动生成类上工作



解释

我使用xsd.exe工具生成一个基于XSD(定义XML文件的模式(的类API,从中与XML文件交互。

这个工具工作得很好,但问题是我有一些模式,这些模式大体上与小的调整相同,所以我想创建接口或抽象类,允许我在其他地方重用代码。

在下面的例子中,为了在这里共享,我简化了生成的代码,但原则仍然适用。

非功能代码示例

程序.cs

public static void Main()
{
BaseColor baseColor = new Color1 { ColorDescription = "Red" };
BaseShape baseShape = new Shape1 { Content = baseColor };
}

Models.cs

//Auto generated models - I have no control over these but they are partial classes
//First set of autogenerated models, normally in its own file
public partial class Shape1
{
public Color1 Content { get; set; }
}
public partial class Color1
{
public string ColorDescription { get; set; }
}
//Second set of autogenerated models, normally in its own file
public partial class Shape2
{
public Color2 Content { get; set; }
}
public partial class Color2
{
public string ColorDescription { get; set; }
}
//Attemping to abstract these classes so I can generically use them regardless of underlying type
public abstract class BaseShape
{
public abstract BaseColor Content { get; set; }
}
public abstract class BaseColor
{
public abstract string ColorDescription { get; set; }
}
//Attempting to extend the autogenerated classes with the abstract classes
public partial class Shape1 : BaseShape { }
public partial class Color1 : BaseColor { }
public partial class Shape2 : BaseShape { }
public partial class Color2 : BaseColor { }

错误

对于两种形状、两种颜色和两种获取/设置方法,此错误总共重复8次。

'Shape1' does not implement inherited abstract member 'BaseShape.Content.set'   XmlSerializeChild

并从CCD_ 2方法得到。

Cannot implicitly convert type 'XmlSerializeChild.Models.BaseColor' to 'XmlSerializeChild.Models.Color1'. An explicit conversion exists (are you missing a cast?)

您的位置非常接近,但正如TheGeneral在评论中所写,在重写属性时无法更改属性的类型。

你可以做的是引入一个新的属性(我已经选择使用接口,但它与抽象类一样好用(,它将在代码中使用,在每个分部类中都有显式的强制转换:

因此,首先,我创建了接口:

public interface IColor { string ColorDescription { get; set; } }
public interface IShape { IColor BaseContent { get; set; } }

然后,将IColor实现添加到Color1Color2类中:

public partial class Color1 : IColor {}
public partial class Color2 : IColor {}

(这是容易的部分,因为ColorDescription对于两种颜色都是相同的类型(。

接下来,我将IShape实现添加到Shape1Shape2类中:

public partial class Shape1 : IShape 
{
public IColor BaseContent
{
get { return Content; }
set { Content = (Color1) value; }
}
}
public partial class Shape2 : IShape 
{
public IColor BaseContent
{
get { return Content; }
set { Content = (Color2) value; }
}
}

现在,在Main方法中,您可以执行以下操作:

var baseColor = new Color1() { ColorDescription = "Red" };
var baseShape = new Shape1() { BaseContent = baseColor };

另一个选项是隐式实现IShape接口,而不是引入新属性,但这会更麻烦,并且不允许使用new Shape1() {Content = baseColor}语法。尽管如此,让我们也回顾一下这个选项:

因此,我们将IShape接口中的BaseContent属性重命名为:

interface IShape { IColor Content { get; set; } }

我们是这样实现的:

public partial class Shape1 : IShape 
{
IColor IShape.Content 
{
get { return ((Shape1)this).Content; }
set { ((Shape1)this).Content = (Color1) value; }
}
}
public partial class Shape2 : IShape 
{
IColor IShape.Content 
{
get { return ((Shape2)this).Content; }
set { ((Shape2)this).Content = (Color2) value; }
}
}

然后,我们创建这样的虔诚:

var baseColor = new Color1() { ColorDescription = "Red" };
// Note: Do not use var here - you need the reference to be of type `IShape`!
IShape baseShape = new Shape1();
baseShape.Content = baseColor;

最新更新