C#:将多态性添加到生成的部分类/属性中

时间:2018-03-01 18:35:09

标签: c# polymorphism

如何在C#中为生成的类添加(非平凡的)多态实现?

例如,假设我的(不可修改的)生成器吐出一百个看起来像这样的类:

public partial class Table1 {
    public int StatusID { get; set; }
    // other properties, etc.
}

我想将这个属性添加到所有这些属性中:

public enum Statuses {
    Unknown,
    Good,
    Error
}

public Statuses Status {
    get { return (Statuses)StatusID; }
    set { StatusID = (int)value; }
}

我该怎么做?我不能使用基类,因为在生成的属性上需要overrides。我不能使用接口,因为我想要实现,而不仅仅是定义。

1 个答案:

答案 0 :(得分:0)

您所描述的是mixin,如果没有IL编织(编译时)或动态代理(运行时),它在C#中不可用。

编译时间mixin

基本上,您生成的类将存在于特殊程序集中,并且该属性将在编译器运行时添加。此特殊属性在程序集本身中不可见,但对程序集的使用者/用户可见。有CiladorMixins.Fody - 都是免费的,但都没有维护/停止。还有PostSharp是商业版,但提供了一个免费版本,也可以获得这个版本。

动态代理

这里的目标会有所不同 - 使用代理将运行时类型替换为动态生成的类型。在框架中,可以使用RealProxy,可以使用dotnet核心DispatchProxy。在这两种情况下,这将比编译时mixin更不好用,我认为最好向你展示而不是解释:

Table1 table = ...

// this creates a proxy (dynamic type) which derives from Table1. This can be used to wrap ANY type with a status property
Table1 proxy = ProxyGenerator.WrapConcreteWithStatusProxy(table);

// the IStatusObject interface and implementation is being provided by the proxy, and is only accessible via a cast.
IStatusObject tableStatus = (IStatusObject)proxy;
tableStatus.Status = Statuses.Good;

如果您熟悉发射IL,则可以使用此方法实现高水平的自定义。

<强>要点:

我在编译时混音方面没那么成功 - 免费的oss停止了库不能开箱即用,商业免费选项有限,尽管它们运行良好。从理论上讲,编译时mixin是更好的选择,因为它们可以提高性能,智能感知并避免运行时转换。

也就是说,动态代理肯定会工作并且更可靠。我在几十个项目中以这种或类似的方式使用了动态代理 - 在很多项目中我通过发送IL来自己生成动态类型。这也为您提供了使用status属性包装任何类型的额外好处,即使您在编译时不了解基类型也是如此。祝你好运!