# C#: custom attributes and altering runtime behaviour

This topic is 3997 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm currently writing my NetObject class and I got the idea of using C# attributes to mark properties as data that needs to be replicated over the network. Like this:
    public class NetObject
{
public NetObject(uint id)
{
this.id = id;
}

[NetProperty]
public uint Id
{
get { return id; }
}

[NetProperty]
public Vector3 Position
{
get { return position; }
set { position = value; }
}

private uint id;
private Vector3 position;
}

In order to not send redundant information over the network I want to mark properties as "dirty". For example, of the setter of Position is called, then the Position property is marked as dirty and will be sent over the network. Can this be created with custom attributes without adding logic to the getters/setters of the properties?

##### Share on other sites
You might be able to get something working like that, though I suspect not without doing some sort of scan every so often to see if the data matches some cache of what was last sent. You're more likely going to have to hook in events to the setters and use the attribute to do automated listener attachment for the netSend/Recv to those.

I do that sort of setup for my hobby game and it... mostly works. There's some danger in doing the events since you can't have them static (globals are bad mmmkay) but you don't want them per instance either. And there's some tedium in the property setup since I've not seen a way short of code generation to create a 'event throwing' property that is reusable.

I also do attribute tagging for the definition of Fog of War requirements. That works much better.

##### Share on other sites
Quote:
 Original post by TelastynYou might be able to get something working like that, though I suspect not without doing some sort of scan every so often to see if the data matches some cache of what was last sent. You're more likely going to have to hook in events to the setters and use the attribute to do automated listener attachment for the netSend/Recv to those.

The scanning bit is a big no-no. No...

Hooking in events could work, but it's something I would like to avoid as I would have to add it to every setter.
And there is another catch. If the type of the object of the Property is a class, a Vector for example, and you change the member of that class, (NetObject.Vector.x) for example, then the setter (NetObject.Vector) is not called. So I would still have to set it dirty manually or make sure all updates go through the setter.
This seems rather error prone to me.

Quote:
 I do that sort of setup for my hobby game and it... mostly works. There's some danger in doing the events since you can't have them static (globals are bad mmmkay) but you don't want them per instance either.

Just a thought, why not make the property call a method on your "PropertyChangedManagerThingy" rather than have the property throw an event.
Such as:
int MyProperty{  set  {    myProperty = value;    propertyChangeManagerThingy.PropertyChanged(this, thisPropertyName, value);  }}

At least then you're not creating numerous instances of delegates/events.

I haven't made up my mind yet about how to solve this. But I'm leaning towards the "old-fashioned" solution by explicitly setting the dirty flags manually in the update. The main reason is that it is possible that the setter is never called when the Property type is a class and its members are updated directly.

##### Share on other sites
Quote:
 Original post by StructuralCan this be created with custom attributes without adding logic to the getters/setters of the properties?
No. Attributes are per-type. Dirtiness information has to be per-object, therefore attributes alone are insufficient.

I would just go for your "old-fashioned" solution of using dirty flags. I couldn't think of a straightforward and sensible way involve attributes given the scenario.

##### Share on other sites
Quote:
Original post by Structural
Quote:
 Original post by TelastynYou might be able to get something working like that, though I suspect not without doing some sort of scan every so often to see if the data matches some cache of what was last sent. You're more likely going to have to hook in events to the setters and use the attribute to do automated listener attachment for the netSend/Recv to those.

The scanning bit is a big no-no. No...

Hooking in events could work, but it's something I would like to avoid as I would have to add it to every setter.
And there is another catch. If the type of the object of the Property is a class, a Vector for example, and you change the member of that class, (NetObject.Vector.x) for example, then the setter (NetObject.Vector) is not called. So I would still have to set it dirty manually or make sure all updates go through the setter.
This seems rather error prone to me.

Why is Vector mutable in the first place, or Vector.x not a similarly throwing property? It is not too terribly error prone, but yes; not ideal.

Quote:

Quote:
 I do that sort of setup for my hobby game and it... mostly works. There's some danger in doing the events since you can't have them static (globals are bad mmmkay) but you don't want them per instance either.

Just a thought, why not make the property call a method on your "PropertyChangedManagerThingy" rather than have the property throw an event.
Such as:
int MyProperty{  set  {    myProperty = value;    propertyChangeManagerThingy.PropertyChanged(this, thisPropertyName, value);  }}

At least then you're not creating numerous instances of delegates/events.

Initially because having levels of events would allow for easier spell effect application and better allow the UI not to poll. I'm not sure these days. I dislike the manager dependency, and I imagine it might have problems distinguishing between client and server contexts when done on the same machine. And the setter isn't the only place that needs the info. Putting that into an attribute allows the 'catcher' to setup the appropriate network processing bits to set the properties as they come in.

Who knows? It might indeed prove too heavyweight once I get enough going to see the impact.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 31
• 16
• 11
• 10
• 11
• ### Forum Statistics

• Total Topics
634113
• Total Posts
3015592
×