Beispiel #1
0
 static void CheckMarkedAsOwned( Owns o, FieldInfo field )
 {
     Debug.Assert
         ( o != null
         , "Field "+field+" of "+field.DeclaringType+" is not marked with Industry.Owns(true|false)"
         , "The field is of a static type of *, IEnumerable<*>, or IDictionary<*>"
         + " (where * implements IDisposable) but is not marked with the attribute Industry.Owns."
         );
 }
Beispiel #2
0
 void EmitDisposeFor_Failed( FieldInfo field, Owns owns )
 {
     throw new InvalidOperationException( "Member "+field.Name+" is not an IDisposable, IDictionary, or IEnumerable but is marked with [Owns]" );
 }
Beispiel #3
0
            void EmitDisposeForIEnumerable( FieldInfo field, Owns owns )
            {
                Type value = null;

                foreach ( var iface in field.FieldType.GetInterfaces() )
                if ( iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IEnumerable<>) )
                {
                    var args = iface.GetGenericArguments();
                    value = args[0];
                    break;
                }

                if ( value != null ) {
                    // We were able to infer generic interface parameters

                    var valueIsDisposable = value.GetInterface(typeof(IDisposable).FullName) != null;
                    //var valueIsDisposable = value.IsSubclassOf(typeof(IDisposable));

                    if ( !valueIsDisposable ) return; // skip emitting anything for this member
                    CheckMarkedAsOwned( owns, field );
                    if ( owns.Key == false ) return; // skip emitting anything for this member
                } else if ( owns == null || !owns.Key ) {
                    return; // We weren't able to infer generic interface parameters AND the member isn't marked as Owned.  Skip it.
                }

                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.Emit( OpCodes.Ldnull );
                il.Emit( OpCodes.Ceq );
                Label islistnull = il.DefineLabel();
                il.Emit( OpCodes.Brtrue, islistnull );

                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.EmitCall( OpCodes.Call, typeof(Internal.RAIIMethods).GetMethod("DisposeOfEnumerable", BindingFlags.Public | BindingFlags.Static), null );

                il.MarkLabel( islistnull );
            }
Beispiel #4
0
            void EmitDisposeForIDisposable( FieldInfo field, Owns owns )
            {
                CheckMarkedAsOwned( owns, field );
                if ( owns.Key == false ) return; // skip emitting anything for this member

                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.Emit( OpCodes.Ldnull );
                il.Emit( OpCodes.Ceq );
                Label isnull = il.DefineLabel();
                il.Emit( OpCodes.Brtrue, isnull );

                var dispose = typeof(IDisposable).GetMethod( "Dispose" );
                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.EmitCall( OpCodes.Call, dispose, null );

                il.MarkLabel( isnull );
            }
Beispiel #5
0
            void EmitDisposeForIDictionary( FieldInfo field, Owns owns )
            {
                Type key = null;
                Type value = null;

                foreach ( var iface in field.FieldType.GetInterfaces() )
                if ( iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(Dictionary<,>) )
                {
                    var args = iface.GetGenericArguments();
                    key   = args[0];
                    value = args[1];
                    break;
                }

                if ( key != null || value != null ) {
                    // We were able to infer generic interface parameters

                    var keyIsDisposable   = key  .GetInterface(typeof(IDisposable).FullName) != null;
                    var valueIsDisposable = value.GetInterface(typeof(IDisposable).FullName) != null;

                    if ( !keyIsDisposable && !valueIsDisposable ) return; // skip emitting anything for this member
                    CheckMarkedAsOwned( owns, field );
                    if ( owns.Key == false && owns.Value == false ) return; // skip emitting anything for this member
                } else if ( owns == null || (!owns.Key && !owns.Value) ) {
                    return; // We weren't able to infer generic interface parameters AND the member isn't marked as Owned.  Skip it.
                }

                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.Emit( OpCodes.Ldnull );
                il.Emit( OpCodes.Ceq );
                Label isdictnull = il.DefineLabel();
                il.Emit( OpCodes.Brtrue, isdictnull );

                il.Emit( OpCodes.Ldarg_0 );
                il.Emit( OpCodes.Ldfld, field );
                il.Emit( owns.Key  ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0 );
                il.Emit( owns.Value? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0 );
                il.EmitCall( OpCodes.Call, typeof(Internal.RAIIMethods).GetMethod("DisposeOfDictionary", BindingFlags.Public | BindingFlags.Static), null );

                il.MarkLabel( isdictnull );
            }
Beispiel #6
0
            public Disposer Create()
            {
                foreach ( var field in type.GetFields(flags) ) {
                    var attribs = field.GetCustomAttributes( typeof(Owns), false );
                    Debug.Assert( attribs.Length <= 1 );

                    var FieldType = field.FieldType;
                    Owns owns = null;
                    if ( attribs.Length != 0 ) owns = attribs[0] as Owns;
                    else if ( type.IsSubclassOf( field.DeclaringType ) ) owns = new Owns(false);

                    if ( field.FieldType.GetInterface(typeof(IDisposable).FullName) != null )        EmitDisposeForIDisposable( field, owns );
                    else if ( field.FieldType.GetInterface(typeof(IDictionary).FullName) != null )   EmitDisposeForIDictionary( field, owns );
                    else if ( field.FieldType.GetInterface(typeof(IEnumerable).FullName) != null )   EmitDisposeForIEnumerable( field, owns );
                    else if ( owns != null && ( owns.Key || owns.Value ) )                           EmitDisposeFor_Failed    ( field, owns );
                }
                il.Emit( OpCodes.Ret );
                return method.CreateDelegate(typeof(Disposer)) as Disposer;
            }