Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Use attribute as processor for get/set

Discussion in 'Scripting' started by qwertyuiop11110, Apr 16, 2020.

  1. qwertyuiop11110

    qwertyuiop11110

    Joined:
    Mar 16, 2020
    Posts:
    24
    There are certain variables which require same processing whenever they're get/set.
    Code (CSharp):
    1. public class testAttribute : MonoBehaviour
    2. {
    3.  
    4.    [AttributeUsage(AttributeTargets.Field, Inherited = false)]
    5.    public class TestingAttribute : Attribute
    6.    {
    7.        public TestingAttribute([CallerMemberName] string propertyName = null)
    8.        {
    9.            Debug.Log(propertyName);
    10.            var abc = typeof(testAttribute).GetField(propertyName);
    11.  
    12.            // int outcome = abc.actuallyReadIt() * 2;
    13.            // Debug.Log(outcome);             // 0, 10, 20, 30, 40
    14.        }
    15.    }
    16.  
    17.  
    18.    [Testing]
    19.    float myField = 0.0f;
    20.  
    21.  
    22.    public void Awake()
    23.    {
    24.        StartCoroutine(iex());
    25.    }
    26.  
    27.    public void Update()
    28.    {
    29.        Debug.Log(myField);
    30.    }
    31.  
    32.    IEnumerator iex()
    33.    {
    34.        while (true)
    35.        {
    36.            myField += 5;
    37.            yield return new WaitForSeconds(1);
    38.        }
    39.    }
    40.  
    41. }
    42.  
    Is it possible to have
    TestingAttribute
    execute whenever
    myField
    is read from or assigned to (beside actually updating the variable), and actually passing the new value to the attribute?

    Without get/set on the field itself. Without invoking external functions (the processing should be in attribute itself). Without using Dictionary and Key method.
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    I believe you want to use properties.
    Code (CSharp):
    1. private float myFloat = 0f;
    2. public float MyFloat{
    3.     get {
    4.         TestingAttribute(); // or whatever else you want to happen when myFloat is read
    5.         return myFloat;
    6.     }
    7.     set {
    8.         myFloat = value;
    9.         TestingAttribute(); // or whatever else you want to happen when myFloat is assigned
    10.     }
    11. }
     
  3. qwertyuiop11110

    qwertyuiop11110

    Joined:
    Mar 16, 2020
    Posts:
    24
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Sure, but what exactly do you plan on doing then? Why is that a requirement?
    You want something to happen on assignment and on read. That's exactly what properties are for. You need to catch the process of reading and assigning a value in order to be able to do something else on read / assign. A private variable which can only be accessed through a public property is doing exactly that.

    If the above does not fulfill your requirements, i assume it's about performance?
    Otherwise it may help if you explained what the use case actually is.
     
    qwertyuiop11110 and PraetorBlue like this.
  5. qwertyuiop11110

    qwertyuiop11110

    Joined:
    Mar 16, 2020
    Posts:
    24
    I need a uniform way to process variables which will identify themselves and provide their new value to that processor, but:
    - I'm not allowed to clutter code with functionality which isn't fulfilling its purpose (i.e. no get/set policy).
    - Cannot use
    Dictionary["myVar"]
    because it is prone to typos and I would need to cast everything everywhere as well as guess names.
    - Cannot use a single function to assign and process the variable, because it will make me do option 2 and/or reflection.

    Which brings me to attributes. Which in some cases can do some processing. I can read the variable through reflection, I can write the variable through reflection, but I don't know its new value which is required for processing.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    That's a dumb policy. If you need getting something to have a side-effect, you should just write the code that has that side-effect in the normal way (getter, or private+get method)
     
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,385
    Is this like an exam question?

    Do you work somewhere and your boss made this requirement?

    Where did this limitation/policy come from?

    ...

    Attributes just hold meta data. They don't actually always exist, they aren't aware of every object instance of the types it has annotated, none of that. It's all there to be something that can be reflected out of the type to get meta data on its parts.

    Of course there are tools out there that have used the meta annotation to do some pretty nifty stuff in the direction you're talking. For example 'PostSharp' lets you use attributes to inject implementation like logging/etc into things like properties/methods/etc. Making it appear as if you just annotated the member yet you get things like logging/validation/etc when it's read/write. BUT how this is actually accomplished is that after the C#/VB is compiled to CIL, the PostSharp post-compiler analyzes the CIL and injects the necessary code.

    Effectively it is using properties and calling functions etc etc. It just doesn't visually look like you did in the code because it's injected in 'post' (hence the name).

    ...

    Mind you I have no idea if things like PostSharp work with Unity considering the compilation pipeline of Unity is very different from how C# is compiled in say VisualStudio. Unity often does things like IL2CPP depending its target platform, and you'd have to get PostSharp to inject its code BEFORE IL2CPP ran.
     
    PraetorBlue and qwertyuiop11110 like this.