Представлен базовый интерфейс, а так же класс:
public interface IObject : IDisposable
{
IntPtr Handle { get; }
}
internal abstract class Object<TAlloc, TDeleter> : IObject
where TAlloc : Delegate where TDeleter : Delegate
{
private SafeLibrary _lib;
protected Object(SafeLibrary library)
{
if (library.IsInvalid || library.IsClosed) throw new AccessUnloadedLibraryException(nameof(library));
_lib = library;
GC.KeepAlive(this);
}
protected bool Valid => Handle != IntPtr.Zero;
protected TAlloc Allocator => As<TAlloc>();
protected TDeleter Deleter => As<TDeleter>();
public IntPtr Handle { get; protected set; }
protected string Error
{
get
{
unsafe
{
return Extensions.GetString(As<GetError>().Invoke(), Encoding.UTF8);
}
}
}
protected TDelegate As<TDelegate>() where TDelegate : Delegate
{
return _lib.Resolve<TDelegate>();
}
#region IDisposable Support
protected bool DisposedValue;
protected virtual void Dispose(bool disposing)
{
if (DisposedValue) return;
if (disposing) Handle = IntPtr.Zero;
_lib.Close();
_lib = null;
DisposedValue = true;
}
~Object()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
Далее приложу один из классов наследников, дабы создать проблемную ситуацию
internal partial class RendererBase : Object<CreateRenderer, DestroyRenderer>
{
private readonly IWindow _window;
public RendererBase(IWindow window, RendererInfo renderInfo, RendererFlags flags) :
#if !WIN64 && !WIN32
base(WinApi.LoadLibrary($"{(IntPtr.Size == 4 ? "x86" : "x64")}\\{Libraries.Sdl2}"))
#else
base(WinApi.LoadLibrary(Libraries.Sdl2))
#endif
{
_window = window;
int id = renderInfo.RendererName == string.Empty
? -1
: ((WindowBase) _window).AvailableRenderers.First(info => info.Value.RendererName == renderInfo.RendererName)
.Key;
Handle = Allocator.Invoke(window.Handle, id, flags);
if (Handle == IntPtr.Zero) throw new Exception(Error);
}
public RendererBase(IWindow window, RendererFlags flags)
: this(window, new RendererInfo(), flags)
{
}
/// <summary>
/// If you want to override this method, do not forget to call <code>base.Dispose(disposing);</code> After your code.
/// </summary>
protected override void Dispose(bool disposing)
{
// TODO: If you want to override this method, do not forget to call "base.Dispose(disposing)." After your code.
if (DisposedValue)
return;
Deleter.Invoke(Handle);
base.Dispose(disposing);
}
}
Allocator.Invoke(...);
Можно ли не модифицируя базовый класс, а так же интерфейс реализовать некоторое дополнительное поле, которое бы на основе переданного типа аллокатора, решало какой из типов подставить в тип TAlloc
Или придется описывать 2 наследника на основе переданного типа в TAlloc
, при этом функциональность остается все та же?
Прилагаю граф зависимости объектов, и ступор на котором все остановилось:
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Приподключении к БД возникла следующия ошибка
Пишу консольное приложение на C#, очень нужно перенести его на сервер под Linux Ubuntu, но не знаю какСлышал о проекте под названием Mono, но не понимаю...
Всем добрый день! У меня проект, WinForms вместе с DevExpressВ своем компьютере без проблем и хорошо работает (и в нем было собран и устанавливал компоненты,...