Skip to content

Instantly share code, notes, and snippets.

@lemonmojo
Last active June 28, 2016 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lemonmojo/f8b7f3bd80f264e65293cd0a5cbaa825 to your computer and use it in GitHub Desktop.
Save lemonmojo/f8b7f3bd80f264e65293cd0a5cbaa825 to your computer and use it in GitHub Desktop.
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