Сама идея родилась
здесьАвтор: 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);
}
}
}
}
}