问题
I'm trying to find how to add functionality to C# structures, and in a more elegant way than just wrapping them in entirely new classes. An extension method just isn't as powerful as an override, and most definitely cannot give a struct event firing/handling capabilities either.
The specific problem I'm currently facing however is detecting and reacting to changes in a Vector2 structure's members. This is only an internal requirement though, so users of my library should be able to use/perceive only Vector2 structures when interacting with it (while still setting off internal events).
Generally, how can I extend C# structures other than by extension methods or encapsulation?
Specifically, how can I extend the Vector2 structure to support event firing/handling?
回答1:
Generally, how can I extend C# structures other than by extension methods or encapsulation?
The only way is to create extension methods or use encapsulation.
Specifically, how can I extend the Vector2 structure to support event firing/handling?
As I said previously you can use encapsulation and create a class. So use this code:
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);
}
}
Then you can add interfaces, methods and events.
EDIT :
But how would I detect if X or Y changes? Say the user "gets" the Vector, and then sets one of its members (X or Y). I could add event firing for when the Vector as a whole is set, but not when one of it's members are set after a 'get.' Keep in mind that I don't want to force the user to use a new vector class in order to interact with my library. I don't even want him/her to have to know that a new vector class is being used internally.
Firstly if you want to mask completely that internally is used a structure of type Vector2
you should rewrite all methods in this way:
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);
}
}
For more info look here.
Now it's simple if you want to create an event that is fired when one members changes. I'd create a costumized EventArgs. Let's write some code:
//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;
}
}
Then you can write your own event:
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
}
来源:https://stackoverflow.com/questions/12173723/adding-functionality-to-c-sharp-structures