【问题标题】:C# Extend class by adding properties [duplicate]C#通过添加属性扩展类[重复]
【发布时间】:2013-07-11 01:47:07
【问题描述】:

在 C# 中是否可以通过添加属性而不是仅添加函数来扩展类。例如:我有一个我依赖的标准 DLL 库,而供应商不想修改它。

在整个代码中,我已经广泛使用了 DataCell 类,直到现在才意识到我需要向它添加一个额外的属性,因为创建一个从该类继承的新扩展类看起来并不像它可以工作 + 一个很多重写。

DataCell [元数据]

public class DataCell : Message
{
public int Field1;
public int Field2;
public DataCell()
{
 ..
} 
..
}

基本上我想添加一个 public int Flags;到这堂课。所以我现在可以不用重写任何东西,(new DataCell).Flags = 0x10;

【问题讨论】:

  • 你不能有扩展属性,但你可以继承一个类并添加属性
  • 在这种情况下,“扩展”是什么意思?你有源代码吗?或者你想使用扩展属性(你不能)?还是从 DataCell 继承好吗?
  • 通过扩展我的意思是这个类在我正在使用的供应商 .dll 库中大量使用。像 ExtDataCell 一样创建:DataCell 不是一个选项,因为我基本上需要重写 .dll 库。所以我希望以某种方式能够做到这一点,以便供应商.dll 中的 DataCell 可以拥有它没有 atm 的属性标志。 (不修改供应商 dll)

标签: c# oop


【解决方案1】:

首先,您可能应该重新考虑您的方法。 但是,如果所有其他方法都失败了,您可以在某种程度上将属性添加到密封类:

using System;
using System.Runtime.CompilerServices;

namespace DataCellExtender
{

    #region sample 3rd party class
    public class DataCell
    {
        public int Field1;
        public int Field2;
    }
    #endregion

    public static class DataCellExtension
    {
        //ConditionalWeakTable is available in .NET 4.0+
        //if you use an older .NET, you have to create your own CWT implementation (good luck with that!)
        static readonly ConditionalWeakTable<DataCell, IntObject> Flags = new ConditionalWeakTable<DataCell, IntObject>();

        public static int GetFlags(this DataCell dataCell) { return Flags.GetOrCreateValue(dataCell).Value; }

        public static void SetFlags(this DataCell dataCell, int newFlags) { Flags.GetOrCreateValue(dataCell).Value = newFlags; }

        class IntObject
        {
            public int Value;
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            var dc = new DataCell();
            dc.SetFlags(42);
            var flags = dc.GetFlags();
            Console.WriteLine(flags);
        }
    }
}

请不要这样做,除非你真的必须这样做。如果您跳过了一个更简洁的解决方案,转而采用这种略显老套的方法,那么此代码的未来维护者可能会对您有一些强烈的评价。

【讨论】:

  • 这绝对是一个有趣的解决方法。我会先探索更清洁的选择,但至少值得考虑。
  • @JonSkeet 啊,是的,我忘了明确提到这是多么糟糕,不应该这样做。我将在其中进行编辑。
  • 哇,这个问题的浏览量达到了 10k。接受这个作为最佳答案,因为这似乎是我当时需要的。不确定性能。
  • +100 它的要点是,如果您将对象的引用作为键存储在ConditionalWeakTable 中,那么如果该对象的所有实例都在其他地方被删除,则该条目将被删除。这允许我们将元数据与密封类相关联,使元数据看起来是类的一部分,但不必处理在其他地方删除元数据后删除该元数据的复杂性。 docs.microsoft.com/en-us/dotnet/api/… 和更多信息stackoverflow.com/questions/18465630/…
  • @ZackMorris 是的。您可以代表其他对象保留一些数据。您可以通过扩展方法访问数据。您可以通过删除相关对象“神奇地”擦除数据。这是hacky,但它的工作原理。 :) 不过,我认为贝尔丁先生不会同意。
【解决方案2】:

好吧,您当然可以扩展一个类,并且只向它添加字段/属性(尽管根据您的示例,我不鼓励使用公共字段)。但是,除非其他代码使用您的新类,否则这些字段不会存在于创建的对象中。例如,如果其他代码有:

DataCell cell = new DataCell();

那么不会有你的Field1Field2字段。

如果基类的每一个实例真的应该有这些字段,那么你最好弄清楚如何更改基类而不是扩展它。

如果您想知道是否可以像添加扩展方法一样添加“扩展字段”(例如public static void Foo(this DataCell cell)),那么不,这是不可能的。

【讨论】:

  • 问题是这个类在供应商提供的另一个类中被广泛使用。因此,每次继承扩展类,需要扩展一堆其他类并重写很多。好的,谢谢
  • @VansS:嗯,我仍然不清楚基类是否应该有额外的字段,或者谁拥有基类。但是你不能只为你不拥有的类添加字段。
【解决方案3】:

有两种方法可以向现有类添加属性

  1. 添加部分类,但这对您不起作用,因为部分类应该在同一个程序集中。

  2. 在不同的类中继承这个类,据我所知,这对你来说是一个更好的解决方案。

不,你不能像扩展方法一样使用扩展属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 2016-08-10
    • 2017-11-16
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    相关资源
    最近更新 更多