diff --git a/Eluant/LuaClrObjectValue.cs b/Eluant/LuaClrObjectValue.cs index d8e4995..be45862 100644 --- a/Eluant/LuaClrObjectValue.cs +++ b/Eluant/LuaClrObjectValue.cs @@ -1,10 +1,12 @@ // // LuaClrObjectValue.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -25,6 +27,8 @@ // THE SOFTWARE. using System; +using System.Linq; +using Eluant.ObjectBinding; namespace Eluant { @@ -54,6 +58,15 @@ public override string ToString() internal abstract object BackingCustomObject { get; } + internal abstract MetamethodAttribute[] BackingCustomObjectMetamethods(LuaRuntime runtime); + + static internal MetamethodAttribute[] Metamethods(Type backingCustomObjectType) + { + return backingCustomObjectType.GetInterfaces() + .SelectMany(iface => iface.GetCustomAttributes(typeof(MetamethodAttribute), false).Cast()) + .ToArray(); + } + internal override object ToClrType(Type type) { if (type == null) { throw new ArgumentNullException("type"); } diff --git a/Eluant/LuaCustomClrObject.cs b/Eluant/LuaCustomClrObject.cs index 76d0cb0..946cffc 100644 --- a/Eluant/LuaCustomClrObject.cs +++ b/Eluant/LuaCustomClrObject.cs @@ -1,10 +1,12 @@ // // LuaCustomClrObject.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -25,6 +27,7 @@ // THE SOFTWARE. using System; +using Eluant.ObjectBinding; namespace Eluant { @@ -51,6 +54,13 @@ internal override object BackingCustomObject { get { return ClrObject; } } + + private MetamethodAttribute[] metamethods; + + internal override MetamethodAttribute[] BackingCustomObjectMetamethods(LuaRuntime runtime) + { + return metamethods ?? (metamethods = runtime.CachedMetamethods(BackingCustomObject.GetType())); + } } } diff --git a/Eluant/LuaOpaqueClrObject.cs b/Eluant/LuaOpaqueClrObject.cs index 98ec940..b6ebd45 100644 --- a/Eluant/LuaOpaqueClrObject.cs +++ b/Eluant/LuaOpaqueClrObject.cs @@ -1,10 +1,12 @@ // // LuaOpaqueClrObject.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -25,6 +27,7 @@ // THE SOFTWARE. using System; +using Eluant.ObjectBinding; namespace Eluant { @@ -51,6 +54,11 @@ internal override object BackingCustomObject { get { return null; } } + + internal override MetamethodAttribute[] BackingCustomObjectMetamethods(LuaRuntime runtime) + { + return null; + } } } diff --git a/Eluant/LuaReference.cs b/Eluant/LuaReference.cs index b5088c6..1a16d50 100644 --- a/Eluant/LuaReference.cs +++ b/Eluant/LuaReference.cs @@ -1,10 +1,12 @@ // // LuaReference.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -50,6 +52,7 @@ internal LuaReference(LuaRuntime runtime, int reference) public sealed override void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) diff --git a/Eluant/LuaRuntime.cs b/Eluant/LuaRuntime.cs index b1d97e9..edbe744 100644 --- a/Eluant/LuaRuntime.cs +++ b/Eluant/LuaRuntime.cs @@ -1,10 +1,12 @@ // // LuaRuntime.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -76,6 +78,7 @@ protected GCHandle SelfHandle private const string OPAQUECLROBJECT_METATABLE = "eluant_opaqueclrobject"; private Dictionary metamethodCallbacks = new Dictionary(); + private Dictionary metamethodAttributes = new Dictionary(); private LuaFunction createManagedCallWrapper; @@ -762,10 +765,7 @@ internal void PushCustomClrObject(LuaClrObjectValue obj) LuaApi.lua_settable(LuaState, -3); // For all others, we use MetamethodAttribute on the interface to make this code less repetitive. - var metamethods = obj.BackingCustomObject.GetType().GetInterfaces() - .SelectMany(iface => iface.GetCustomAttributes(typeof(MetamethodAttribute), false).Cast()); - - foreach (var metamethod in metamethods) { + foreach (var metamethod in obj.BackingCustomObjectMetamethods(this)) { LuaApi.lua_pushstring(LuaState, metamethod.MethodName); Push(metamethodCallbacks[metamethod.MethodName]); LuaApi.lua_settable(LuaState, -3); @@ -778,6 +778,19 @@ internal void PushCustomClrObject(LuaClrObjectValue obj) } } + internal MetamethodAttribute[] CachedMetamethods(Type backingCustomObjectType) + { + MetamethodAttribute[] metamethods; + if (metamethodAttributes.TryGetValue(backingCustomObjectType, out metamethods)) { + return metamethods; + } + + metamethods = LuaClrObjectValue.Metamethods(backingCustomObjectType); + metamethodAttributes.Add(backingCustomObjectType, metamethods); + + return metamethods; + } + private int NewindexCallback(IntPtr state) { return LuaToClrBoundary(state, toDispose => { diff --git a/Eluant/LuaTransparentClrObject.cs b/Eluant/LuaTransparentClrObject.cs index 592884b..936136e 100644 --- a/Eluant/LuaTransparentClrObject.cs +++ b/Eluant/LuaTransparentClrObject.cs @@ -1,10 +1,12 @@ // // LuaTransparentClrObject.cs // -// Author: +// Authors: // Chris Howie +// Tom Roostan // // Copyright (c) 2013 Chris Howie +// Copyright (c) 2015 Tom Roostan // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -71,8 +73,15 @@ internal override object BackingCustomObject get { return proxy; } } + internal override MetamethodAttribute[] BackingCustomObjectMetamethods(LuaRuntime runtime) + { + return TransparentClrObjectProxy.Metamethods; + } + private class TransparentClrObjectProxy : ILuaTableBinding, ILuaEqualityBinding { + public static readonly MetamethodAttribute[] Metamethods = LuaClrObjectValue.Metamethods(typeof(TransparentClrObjectProxy)); + private LuaTransparentClrObject clrObject; public TransparentClrObjectProxy(LuaTransparentClrObject obj)