为C#结构添加功能

时间:2012-08-29 08:27:24

标签: c# events design-patterns data-structures extension-methods

我正在尝试找到如何为C#结构添加功能,并且以一种更优雅的方式,而不仅仅是将它们包装在全新的类中。扩展方法不像覆盖那样强大,并且绝对不能给出结构事件触发/处理功能。

我目前面临的具体问题是检测并响应Vector2结构成员的变化。这只是一个内部要求,因此我的库的用户应该能够在与它交互时仅使用/感知Vector2结构(同时仍然设置内部事件)。


通常,除扩展方法或封装外,如何扩展C#结构?

具体来说,如何扩展Vector2结构以支持事件触发/处理?

1 个答案:

答案 0 :(得分:2)

  

通常,我如何扩展C#结构而不是扩展名   方法或封装?

唯一的方法是创建扩展方法或使用封装。

  

具体来说,如何扩展Vector2结构以支持事件   点火/处理

正如我之前所说,你可以使用封装和创建一个类。所以使用这段代码:

public class ExtendedVector2 {
    public Vector2 Vector{
        get;
        private set;
    }

    public ExtendedVector2(float value){
        Vector = new Vector2(value);
    }   

    public ExtendedVector2(float x, float y){
        Vector = new Vector2(x, y);
    }
}

然后你可以添加接口,方法和事件。

编辑:

  

但是我如何检测X或Y是否会发生变化?说用户“得到”了   向量,然后设置其中一个成员(X或Y)。我可以添加活动   设置Vector作为一个整体时触发,但不是当其中一个设置时触发   成员是在“获取”之后设置的。请记住,我不想强​​迫   用户使用新的矢量类以便与我交互   图书馆。我甚至不希望他/她必须知道一个新的载体   class正在内部使用。

首先,如果你想完全掩盖内部使用类型为Vector2的结构,你应该用这种方式重写所有方法:

public class ExtendedVector2 {
    //...
    private Vector2 _vector2;  

    //mask X and Y values of Vector2 structure 
    public float X{
        set{ _vector2.X = value; }
        get{ return _vector2.X; }
    }

    public float Y{
        set{ _vector2.Y = value; }
        get{ return _vector2.Y; }
    } 

    //example to mask a method of Vector2 structure 
    public static float Dot(ExtendedVector2 value1, ExtendedVector2 value2){
        return Vector.Dot(value1, value2);
    }

    //override the cast to Vector2
    public static implicit operator Vector2(ExtendedVector2 value) //I'd make it implicit because I'd think to it like an upcast
    {
        return new Vector2(value.X, value.Y);
    }
}

了解更多信息look here

现在,如果您想创建一个成员更改时触发的事件,这很简单。 我会创建一个costumized EventArgs。我们来写一些代码:

//use the convention of eventName+EventArgs
class MemberChangedEventArgs : EventArgs
{
    public readonly float LastValue{
        get;
        set;
    }
    public readonly float NewValue{
        get;
        set;
    }

    public MemberChangedEventArgs(float LastValue, float NewValue)
    {
        this.LastValue = LastValue;
        this.NewValue = NewValue;
    }
}

然后你可以写自己的事件:

public class ExtendedVector2 {
    private Vector2 _vector2;  

    public float X{
         set{                  
             if(_vector2.X != value)           
               OnMemberXChanged(new MemberChangedEventArgs(_vector2.X, value));

             _vector2.X = value;   
         }
         get{ return _vector2.X; }
    }

    public float Y{
         set{ 
             if(_vector2.Y != value)
               OnMemberYChanged(new MemberChangedEventArgs(_vector2.Y, value));

             _vector2.Y = value;                    
         }
         get{ return _vector2.Y; }
    }        

    public event EventHandler<MemberChangedEventArgs> MemberXChanged;
    public event EventHandler<MemberChangedEventArgs> MemberYChanged;

    public ExtendedVector2(float value){
        Vector = new Vector2(value);
    }   

    public ExtendedVector2(float x, float y){
        Vector = new Vector2(x, y);
    }

    private virtual void OnMemberXChanged(MemberChangedEventArgs e){
        if(MemberXChanged != null)
           MemberXChanged(this, e);
    }

    private virtual void OnMemberYChanged(MemberChangedEventArgs e){
        if(MemberYChanged != null)
           MemberYChanged(this, e);
    }
    //... 

    //here mask the Vector2 structure using the previous solution
}