Using Expression compiles to DynamicMethods - this should be fast as possible - maybe.
Thanks for the suggestion from kornman00 and dave.dolan
class CZipArchive : IDisposable
{
static Func<string, FileMode, FileAccess, FileShare, bool, object> openonfile;
static Func<Stream, FileMode, FileAccess, bool, object> openonstream;
static Func<object, string, object> getfile;
static Func<object, object> getfiles;
static Action<object, string> deletefile;
static Func<object, string, CompressionMethodEnum, DeflateOptionEnum, object> addfile;
object external;
CZipArchive() { }
public static CZipArchive OpenOnFile(string path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read, FileShare share = FileShare.Read, bool streaming = false)
{
if (openonfile == null)
{
var type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipArchive");
var meth = type.GetMethod("OpenOnFile", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var paras = meth.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
openonfile = Expression.Lambda<Func<string, FileMode, FileAccess, FileShare, bool, object>>(Expression.Call(meth, paras), paras).Compile();
}
return new CZipArchive { external = openonfile(path, mode, access, share, streaming) };
}
public static CZipArchive OpenOnStream(Stream stream, FileMode mode = FileMode.OpenOrCreate, FileAccess access = FileAccess.ReadWrite, bool streaming = false)
{
if (openonstream == null)
{
var type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipArchive");
var meth = type.GetMethod("OpenOnStream", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var paras = meth.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
openonstream = Expression.Lambda<Func<Stream, FileMode, FileAccess, bool, object>>(Expression.Call(meth, paras), paras).Compile();
}
return new CZipArchive { external = openonstream( stream, mode, access, streaming) };
}
public enum CompressionMethodEnum : ushort { Stored = 0, Deflated = 8 };
public enum DeflateOptionEnum : byte { Normal = 0, Maximum = 2, Fast = 4, SuperFast = 6 };
public ZipFileInfo AddFile(string path, CompressionMethodEnum compmeth = CompressionMethodEnum.Deflated, DeflateOptionEnum option = DeflateOptionEnum.Normal)
{
if (addfile == null)
{
var type = external.GetType(); var arco = Expression.Parameter(typeof(object));
var meth = type.GetMethod("AddFile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var args = meth.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
var arg1 = Expression.Parameter(typeof(CompressionMethodEnum)); var arg2 = Expression.Parameter(typeof(DeflateOptionEnum));
addfile = Expression.Lambda<Func<object, string, CompressionMethodEnum, DeflateOptionEnum, object>>(Expression.Call(Expression.Convert(arco, type), meth, args[0], Expression.Convert(arg1, args[1].Type), Expression.Convert(arg2, args[2].Type)), arco, args[0], arg1, arg2).Compile();
}
return new ZipFileInfo { external = addfile(external, path, compmeth, option) };
}
public ZipFileInfo GetFile(string name)
{
if (getfile == null)
{
var type = external.GetType(); var arco = Expression.Parameter(typeof(object)); var arg = Expression.Parameter(typeof(string));
var meth = type.GetMethod("GetFile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
getfile = Expression.Lambda<Func<object, string, object>>(Expression.Call(Expression.Convert(arco, type), meth, arg), arco, arg).Compile();
}
return new ZipFileInfo { external = getfile(external, name) };
}
public IEnumerable<ZipFileInfo> Files
{
get
{
if (getfiles == null)
{
var type = external.GetType(); var arco = Expression.Parameter(typeof(object));
var meth = type.GetMethod("GetFiles", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
getfiles = Expression.Lambda<Func<object, object>>(Expression.Call(Expression.Convert(arco, type), meth), arco).Compile();
}
foreach (var p in (System.Collections.IEnumerable)getfiles(external)) yield return new ZipFileInfo { external = p };
}
}
public void DeleteFile(string name)
{
if (deletefile == null)
{
var type = external.GetType(); var arco = Expression.Parameter(typeof(object)); var arg = Expression.Parameter(typeof(string));
var meth = type.GetMethod("DeleteFile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
deletefile = Expression.Lambda<Action<object, string>>(Expression.Call(Expression.Convert(arco, type), meth, arg), arco, arg).Compile();
}
deletefile(external, name);
}
public void Dispose()
{
((IDisposable)external).Dispose();
}
public struct ZipFileInfo
{
static Func<object, FileMode, FileAccess, Stream> getstream;
static Func<object, string> get_name;
static Func<object, DateTime> get_lwt;
internal object external;
public override string ToString()
{
return Name;
}
public string Name
{
get
{
if (get_name == null)
{
var arco = Expression.Parameter(typeof(object));
get_name = Expression.Lambda<Func<object, string>>(Expression.PropertyOrField(Expression.Convert(arco, external.GetType()), "Name"), arco).Compile();
}
return get_name(external);
}
}
public DateTime LastModFileDateTime
{
get
{
if (get_lwt == null)
{
var arco = Expression.Parameter(typeof(object));
get_lwt = Expression.Lambda<Func<object, DateTime>>(Expression.PropertyOrField(Expression.Convert(arco, external.GetType()), "LastModFileDateTime"), arco).Compile();
}
return get_lwt(external);
}
}
public Stream GetStream(FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read)
{
if (getstream == null)
{
var type = external.GetType(); var arco = Expression.Parameter(typeof(object)); var arc1 = Expression.Parameter(typeof(FileMode)); var arc2 = Expression.Parameter(typeof(FileAccess));
var meth = type.GetMethod("GetStream", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
getstream = Expression.Lambda<Func<object, FileMode, FileAccess, Stream>>(Expression.Call(Expression.Convert(arco, type), meth, arc1, arc2), arco, arc1, arc2).Compile();
}
return getstream(external, mode, access);
}
}
}
|