Reputation: 1665
So I would like to create an extension method for a Type that the api has otherwise sealed.
If you know about extension methods the following should look familiar.
private static List<Member> memberList = new List<Member>();
public static List<Member> GetMemberList(this GameObject go)
{
return memberList;
}
Notice that to declare an extension method, it needs to be static, and because it needs to be static, the List that Im accessing through the GameObject type has to be static to. I would like each GameObject to have its own list of Members. However Im pretty sure since this is a static field every instanced GameObject will point to the same static memberList.
So would my assumptions be true? And if so, what might be an alternative? I would like to avoid putting the GameObject in a wrapper class that also holds the memberList because the api only allows GameObjects to be detected and manipulated at runtime. There are ways to reverse reference the wrapper class through the gameObject but that adds a lot more complexity to the code i would like to avoid.
Upvotes: 2
Views: 693
Reputation: 113352
private static ConditionalWeakTable<GameObject, List<Member>> dict = new ConditionalWeakTable<GameObject, List<Member>>();
public static List<Member> GetMemberList(this GameObject go)
{
return dict.GetOrCreateValue(go);
}
ConditionalWeakTable
manages the object lifetime, because it uses weak-references. Therefore it doesn't stop the GC from collecting the GameObject
if it there are no other live references to it, and this will also allow the List<Member>
to be collected.
It is threadsafe, but this assumes that you want your starting point to be an empty list (the default constructor is called in GetOrCreateValue
if there isn't a current value). If you want a different starting point, your threading issues become more complicated.
Upvotes: 1
Reputation: 7375
It appears you are working with Unity3. There is a related answer on the UnityAnswers site that may help: http://answers.unity3d.com/questions/22493/unity-3-sealed-class-gameobject-.html
It appears that there should be ways to attach the behaviors you want inherent in the Unity framework using the builtin scripting system.
Upvotes: 2
Reputation: 2168
Yes, you are right. If you have a static method, all instances of that class share the same data. The call return memberList;
is illegal. It is the same as return this.memberList;
and this
is not available in a static method. Instead you'd have to call the class: return GameObject.memberList;
. But I understand that you are not looking for this solution.
Extension methods are meant to create additional behavior. If you want to create additional data, extending the GameObject class using inheritance is the right choice.
Alternatively you could attach the memberList by using a dictionary of the form Dictionary<GameObject, List<Member>>
. But personally I'd favor composition as shown below:
public class myGameObject
{
public List<Member> memberList { get; set; }
public GameObject go { get; set; }
}
Upvotes: 1
Reputation: 25773
Extension methods are simply just static methods that "appear" to look like instance methods.
They however, do not add any additional functionality a static method doesn't, it's just for ease-of-use, maintenance, and readability. Extension methods cannot access protected / private members either.
If GameObject
is not actually sealed (ie it doesn't have the sealed
keyword), then you can write a class that inherits GameObject
to gain access to its protected methods/fields/properties. This will only work if you yourself are the one constructing these objects.
Upvotes: 0
Reputation: 700690
Yes, if you want to keep something outside the game object and access it through the extension method, it would have to be static.
You can use a dictionary to map one member list to each game object:
private static Dictionary<GameObject, List<Member>> memberLists = new Dictionary<GameObject, List<Member>>();
public static List<Member> GetMemberList(this GameObject go) {
return memberLists[go];
}
Upvotes: 6