C# Attributes – Caller Information

As I started venturing into Unity3D and C# I found myself missing couple of useful preprocessor macros from C. The three macros I was missing the most were __FILE____LINE__ and __FUNCTION__. One could argue that those three are the closest thing to what one could call Reflections in C.

I didn’t know what the equivalent for those macros were or if there even was one in C#. Albeit, I was mainly doing thing inside Unity3D so this wasn’t even an issue. So I did some research on Reflections for the blog and eventually also on Attributes and I stumbled upon this thing called Caller Information.

Although Caller Information isn’t really the same thing as the macros mentioned earlier, I think it’s close enough. With Caller Information you can obtain information about the caller to a method.

Here’s a little example of how those preprocessor macros can be helpful.

printf("[%s:%s()::%d] Warning: Input string is empty\n", __FILE__, __FUNCTION__, __LINE__);
// Output:
//  [utils.c:rstrip()::256] Warning: Input string is empty

Right away you can see where the warning was generated, and if you need to react or even disable the message, you will locate it instantly.

As far as I know, C# doesn’t provide anything similar to this. So, we’re going to make something that produces similar outcome.

using System;
using System.Runtime.CompilerServices;

namespace Attributes_Caller_Information_01 {
    class Program {
        static void Debug(string value, 
            [CallerMemberName] string name = "",
            [CallerFilePath] string filePath = "",
            [CallerLineNumber] int lineNumber = 0) 
        {
            Console.WriteLine("[{0}:{1}()::{2}]\n\t" + value, filePath, name, lineNumber);
        }
        static void Main(string[] args) {
            Debug("Just a simple example");
        }
    }
}

// Output:
// [<pathname>\Program.cs:Main()::16]
//        Just a simple example

There might be a better way for handling this, but for this short post, I think this example is sufficient enough. The important bits here are the CallerMemberNameCallerFilePath and CallerLineNumber, which are part of the System.Runtime.CompilerServices. It’s required that what ever variable is defined after the attribute is defined with a default value. That’s all there is to it.

Unfortunately those attributes cannot be used when calling the method, so you can’t use them like this:

Console.WriteLine("{0}", [System.Runtime.CompilerServices.CallerFilePath]);

For more information about the the Caller Information, check the documentation.

Conclusions

The solution is quite ugly and I might return with a better implementation at some point. I would have liked to extend System.Console.WriteLine() and add Caller Information fields to that extension, but it seems that it’s either impossible or unnecessarily difficult.

Caller Information attributes can still be useful when debugging with a shotgun. Meaning that if you’re really not sure where the issue is within your code, you could insert dozens of Debug() messages and see how far the execution goes. Still, it’s a stupid idea. Using breakpoints and a real debugger would be much better option.

 

 

Unity3D Reflections – Part 2 – Limiting Access

In the last blog post we discussed how to do runtime-coupling or dependency injection using Reflections. I mentioned that I don’t think it’s really safe, because there wasn’t any way to control the injection. You could block the injector with adjusting the protection level for the property or by not using property for holding the reference. I think that’s the wrong way around the problem.

We could leave the disabling of property injection to the component, but don’t really like it. I’d much rather have a system where the user has to enable the injection for the property.

We’re going to use Attributes to handle the enabling of injection for the properties. We’re going to use the project from the last post and add on to it. But first, let’s scratch the surface of Attributes.

Attributes

Attributes are simply a way to attach metadata to your assemblies, types, methods, properties and such. Attributes can be easily accessed with Reflections. Attributes are attached to parts of code with square brackets and you most likely seen them used in Unity3D code.

Couple of examples from unity and C# itself

// Unity specific Attributes
// Hides the public variable from the inspector
[HideInInspector]
public Vector3 direction;

// Displays a header in Unity3d inspector
[Header("Player Health")]
public int health = 0;

// Set's the available range of the variable in the inspector.
[Range(0, 100)] 
public int speed = 0;

// Marks the private field to be serialized
[SerializeField]
private string name = "Some name";

// C# specific attributes
// Marks the class to be serializable
[Serializable]
public class SomeClass { /* ... */ }

// Imports the GetKeyState() method from user32.dll.
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern short GetKeyState(int key);

 

An attribute is defined when a class inherits from System.Attribute class. Today, we will use only the bare minimum to create a CustomAttribute for our example project. For more details about the Attribute class, see Microsoft System.Attribute documentation.

I’m not going to use any of the predefined Attributes here. I’m planning on writing couple of posts about StructLayoutAttribute and as short one on Caller Information. Might do others too, if I find anything interesting.

The code

This is going to be short and simple. The amount of code we have to do to enable the EnableInject-attribute is almost criminal. To begin with, we need to create a class for the attribute. I’m going to call it EnableInjectAttribute.

using System;

[AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple = false)]
public class EnableInjectAttribute : Attribute {
    public EnableInjectAttribute() {

    }
}

The AttributeUsageAttribute isn’t really necessary. It’s used to add limitations to the CustomAttribute. In our case, It makes the EnableInjectAttribute to be only usable with properties. Some of the other possible targets were mentioned in previous part. AllowMultiple part prevents us from using the EnableInject multiple times for a single property. It’s here mainly for displaying the option for enabling or disabling multiple usage.

Now we need to change the Injector itself.

using System.Reflection;
using System.Linq;
using System;

public static class Injector 
{
  // Simple static injector
  public static void InjectProperty<T>(GameObject gameObject, T dependency) 
  {
    // Go through the child objects
    foreach(Transform child in gameObject.transform) 
    { 
      foreach(Component childComponent in 
              child.gameObject.GetComponents<Component>()) 
      {
        // Using the power of LIQN to get the settable properties for 
        // the Components where we can read and write the value and 
        // is of type T
        var properties = childComponent.GetType().GetProperties().Where(
          prop => prop.CanRead && prop.CanWrite).Where(
            prop => prop.PropertyType == typeof(T));

        // If nothing of suitable type is found, properties variable 
        // should be null
        if(properties != null) 
        {
          foreach(PropertyInfo pi in properties) 
          {
            // Use SetValue of System.Reflection.PropertyInfo to set the value
            // of the property
            var a = Attribute.GetCustomAttribute(pi, typeof(EnableInjectAttribute));
            if(a != null) 
            {
              pi.SetValue(childComponent, (object)dependency, null);
            }
          }
        }
      }
    }
  }
}

I decided to show the whole code for clarity’s sake. (The highlight in PrismJS isn’t working correctly. Not sure why.) The code changes are on lines 31-36.

We call the GetCustomAttribute() for the PropertyInfo pi. We are only interested in attributes of type EnableInjectAttribute. Next we just check if the EnableInjectAttribute was found, and inject the dependency.

The last bit of code we need, is the part where we use the EnableInjectAttribute with the RigidBody property.

using UnityEngine;

public class Gravity : MonoBehaviour 
{
  // This is the property we'll be set with Injector.PropertyInject<>()
  [EnableInject]
  public Rigidbody GravityRigidbody 
  {
    get; set;
  }

  public float gravityForce = -9.81f;

  private void FixedUpdate() 
  {
    // Just to be sure, check if GravityRigidbody was set correctly
    if(GravityRigidbody != null) 
    {
      GravityRigidbody.AddForce(Vector3.up * gravityForce, ForceMode.Acceleration);
    }
  }
}

We don’t need to use the Attribute part of the attribute name when using it here.

Whole project is stored in github: https://github.com/jkelanne/Reflections-part_02

Next in the series

I’m probably doing a shorter post next time. It’s about something I ran into while exploring the Attributes: Caller Information. It’s not really needed in Unity3D or at least in the form I’m going to be using it. It’s something I was missing coming from C/C++.