Last active
June 28, 2016 16:29
-
-
Save lemonmojo/f8b7f3bd80f264e65293cd0a5cbaa825 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class Exception_ObjC_Extensions | |
{ | |
public static __ObjC_LMExceptionError ToLMExceptionError(this Exception exception) | |
{ | |
return __ObjC_LMExceptionError.FromException(exception); | |
} | |
} | |
[Register("LMExceptionError")] | |
public class __ObjC_LMExceptionError : NSError | |
{ | |
public static readonly NSString ManagedExceptionErrorDomain = (NSString)"ManagedExceptionErrorDomain"; | |
public Exception Exception { get; set; } | |
public __ObjC_LMExceptionError(Exception exception) : | |
base( | |
ManagedExceptionErrorDomain, | |
exception.HResult, | |
new NSDictionary( | |
NSError.LocalizedDescriptionKey, exception.Message, | |
NSError.HelpAnchorErrorKey, exception.HelpLink | |
) | |
) | |
{ | |
Exception = exception; | |
} | |
public static __ObjC_LMExceptionError FromException(Exception exception) | |
{ | |
if (exception == null) { | |
return null; | |
} | |
return new __ObjC_LMExceptionError(exception); | |
} | |
[Export("exceptionTypeName")] | |
public string ExceptionTypeName | |
{ | |
get { | |
return Exception.GetType().AssemblyQualifiedName; | |
} | |
} | |
[Export("message")] | |
public string Message | |
{ | |
get { | |
return Exception.Message; | |
} | |
} | |
[Export("source")] | |
public string Source | |
{ | |
get { | |
return Exception.Source; | |
} | |
} | |
[Export("stackTrace")] | |
public string StackTrace | |
{ | |
get { | |
return Exception.StackTrace; | |
} | |
} | |
[Export("helpLink")] | |
public string HelpLink | |
{ | |
get { | |
return Exception.HelpLink; | |
} | |
} | |
[Export("innerError")] | |
public __ObjC_LMExceptionError InnerError | |
{ | |
get { | |
if (Exception.InnerException == null) { | |
return null; | |
} | |
return new __ObjC_LMExceptionError(Exception.InnerException); | |
} | |
} | |
#region Try Catch Finally | |
[Export("try:catch:finally:")] | |
public static void TryCatchFinally([BlockProxy(typeof(TryFinallyBlockProxy))] Action tryBlock, [BlockProxy(typeof(CatchBlockProxy))] Action<__ObjC_LMExceptionError> catchBlock, [BlockProxy(typeof(TryFinallyBlockProxy))] Action finallyBlock) | |
{ | |
try { | |
tryBlock(); | |
} catch (Exception ex) { | |
if (catchBlock != null) { | |
catchBlock(ex.ToLMExceptionError()); | |
} | |
} finally { | |
if (finallyBlock != null) { | |
finallyBlock(); | |
} | |
} | |
} | |
[Export("try:catch:")] | |
public static void TryCatch([BlockProxy(typeof(TryFinallyBlockProxy))] Action tryBlock, [BlockProxy(typeof(CatchBlockProxy))] Action<__ObjC_LMExceptionError> catchBlock) | |
{ | |
try { | |
tryBlock(); | |
} catch (Exception ex) { | |
if (catchBlock != null) { | |
catchBlock(ex.ToLMExceptionError()); | |
} | |
} | |
} | |
[Export("try:error:")] | |
public static void TryError([BlockProxy(typeof(TryFinallyBlockProxy))] Action tryBlock, out NSError error) | |
{ | |
error = null; | |
try { | |
tryBlock(); | |
} catch (Exception ex) { | |
error = ex.ToLMExceptionError(); | |
} | |
} | |
[DllImport("/usr/lib/libobjc.dylib")] | |
private static extern IntPtr _Block_copy(IntPtr ptr); | |
[DllImport("/usr/lib/libobjc.dylib")] | |
private static extern void _Block_release(IntPtr ptr); | |
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] | |
private delegate void TryFinallyBlock(IntPtr block); | |
internal class TryFinallyBlockProxy | |
{ | |
private IntPtr m_blockPtr; | |
private TryFinallyBlock m_invoker; | |
[Preserve(Conditional = true)] | |
public unsafe TryFinallyBlockProxy(BlockLiteral* block) | |
{ | |
m_blockPtr = _Block_copy((IntPtr)block); | |
m_invoker = block->GetDelegateForBlock<TryFinallyBlock>(); | |
} | |
[Preserve(Conditional = true)] | |
~TryFinallyBlockProxy() | |
{ | |
_Block_release(m_blockPtr); | |
} | |
[Preserve(Conditional = true)] | |
public unsafe static Action Create(IntPtr block) | |
{ | |
return new TryFinallyBlockProxy((BlockLiteral*)block).Invoke; | |
} | |
[Preserve(Conditional = true)] | |
unsafe void Invoke() | |
{ | |
m_invoker(m_blockPtr); | |
} | |
} | |
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] | |
private delegate void CatchBlock(IntPtr block, IntPtr error); | |
internal class CatchBlockProxy | |
{ | |
private IntPtr m_blockPtr; | |
private CatchBlock m_invoker; | |
[Preserve(Conditional = true)] | |
public unsafe CatchBlockProxy(BlockLiteral* block) | |
{ | |
m_blockPtr = _Block_copy((IntPtr)block); | |
m_invoker = block->GetDelegateForBlock<CatchBlock>(); | |
} | |
[Preserve(Conditional = true)] | |
~CatchBlockProxy() | |
{ | |
_Block_release(m_blockPtr); | |
} | |
[Preserve(Conditional = true)] | |
public unsafe static Action<__ObjC_LMExceptionError> Create(IntPtr block) | |
{ | |
return new CatchBlockProxy((BlockLiteral*)block).Invoke; | |
} | |
[Preserve(Conditional = true)] | |
unsafe void Invoke(__ObjC_LMExceptionError error) | |
{ | |
m_invoker(m_blockPtr, error == null ? IntPtr.Zero : error.Handle); | |
} | |
} | |
#endregion Try Catch Finally | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment