C#: class DisposableType
От: IT Россия linq2db.com
Дата: 15.08.02 17:39
Оценка: 44 (3)
Сама идея родилась здесь
Автор: AndrewVK
Дата: 09.05.02
. DarkGray захотел невозможного, AndrewVK подкинул идею как сделать, я предлагаю свой вариает реализации

Зачем это надо? Конструкция using в C# помогает более/менее хорошо справляться с проблемой освобождения ресурсов для объектов с ограниченным сроком жизни. Например, в данном случае всё будет хорошо:

using (SqlConnection con = new SqlConnection())
{
    ...
}


Но если объект SqlConnection является членом какого либо класса, то using абсолютно бесполезна и помочь ничем не может. Единственный способ — наследоваться от IDisposable и чистить всё ручками. Данный класс позволяет избежать этого и заменить данную процедуру использованием атрибутов:

class MyClass : DisposableType
{
    [Using]
    public SqlConnection con;
}


На данный момент этот механизм может применятся к типам, реализующим IDisposable, COM-объектам, а также массивам и коллекциям таких объектов.

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections;

namespace RSDN
{
    [AttributeUsage(AttributeTargets.Field)]
    public class UsingAttribute: Attribute 
    {
    }

    public abstract class DisposableType: IDisposable
    {
        bool disposed = false;

        ~DisposableType()
        {
            if (!disposed) 
            {
                try 
                {
                    disposed = true;
                    Dispose(false);
                } 
                catch
                {
                }
            }
        }

        public void Dispose()
        {
            if (!disposed) 
            {
                try 
                {
                    disposed = true;
                    Dispose(true);
                    GC.SuppressFinalize(this);
                }
                catch
                {
                }
            }
        }

        public void Close()
        {
            Dispose();
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing) 
            {
                // managed objects
            }
            // unmanaged objects and resources
            DisposeFields(this);
        }

        static public void DisposeFields(object obj)
        {
            foreach (
                FieldInfo field in 
                    obj.GetType().GetFields
                        (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance))
            {
                if (Attribute.IsDefined(field,typeof(UsingAttribute))) 
                {
                    DisposeObject(field.GetValue(obj));
                }
            }
        }

        static protected void DisposeObject(object val)
        {
            if (val != null)
            {
                if (val is IDisposable)
                {
                    ((IDisposable)val).Dispose();
                }
                else if (val.GetType().IsCOMObject)
                {
                    Marshal.ReleaseComObject(val);
                }
                else if (val is IList)
                {
                    IList list = val as IList;
                    foreach (object o in list)
                        DisposeObject(o);
                }
            }
        }
    }
}
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.