19

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

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

DataCell [元数据]

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

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

4

3 回答 3

19

首先,您可能应该重新考虑您的方法。但是,如果所有其他方法都失败了,您可以通过以下方式将属性添加到密封类:

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);
        }
    }
}

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

于 2013-07-12T14:47:11.430 回答
9

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

DataCell cell = new DataCell();

那么那将没有你的Field1Field2领域。

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

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

于 2013-07-12T13:39:31.153 回答
5

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

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

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

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

于 2013-07-12T13:52:47.280 回答