Created
January 30, 2017 06:25
-
-
Save unarist/e32fec3d5fa51e17562d8bc5a2375aba to your computer and use it in GitHub Desktop.
今のMyExtensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
// Write code to test your extensions here. Press F5 to compile and run. | |
} | |
public static class Ex | |
{ | |
public static string CallerMemberName([CallerMemberName]string member = "") => member; | |
public static Func<TR> F<TR>(Func<TR> f) { return f; } | |
public static Func<T, TR> F<T, TR>(Func<T, TR> f) { return f; } | |
public static Action A(Action f) { return f; } | |
public static Action<T> A<T>(Action<T> f) { return f; } | |
public static Action<T1, T2> A<T1, T2>(Action<T1, T2> f) { return f; } | |
public static Func<T> C<T>(T value) => () => value; | |
public static T Id<T>(T v) { return v; } | |
public static Func<T, bool> Eq<T>(T value) where T : IEquatable<T> => x => value.Equals(x); | |
public static Func<T, bool> Neq<T>(T value) where T : IEquatable<T> => x => !value.Equals(x); | |
public static IEnumerable<T> Seq<T>(T value) { yield return value; } | |
public static IEnumerable<T> Seq<T>(params T[] values) => values; | |
public static T[] Arr<T>(params T[] values) => values; | |
public static IEnumerable<T> InfSeq<T>(Func<T, T> next, T initial) | |
{ | |
for(var cur = initial; ; cur = next(cur)) | |
yield return cur; | |
} | |
} | |
public static class Type<T> | |
{ | |
public static T Construct<TArg1>(TArg1 arg1) => | |
(T)typeof(T).GetConstructor(new[] { typeof(TArg1) }).Invoke(new object[] { arg1}); | |
} | |
public static class HardLinkUtils | |
{ | |
[StructLayout(LayoutKind.Sequential)] | |
private struct BY_HANDLE_FILE_INFORMATION | |
{ | |
public uint FileAttributes; | |
public FILETIME CreationTime; | |
public FILETIME LastAccessTime; | |
public FILETIME LastWriteTime; | |
public uint VolumeSerialNumber; | |
public uint FileSizeHigh; | |
public uint FileSizeLow; | |
public uint NumberOfLinks; | |
public uint FileIndexHigh; | |
public uint FileIndexLow; | |
} | |
[DllImport("kernel32.dll", SetLastError = true)] | |
private static extern void GetFileInformationByHandle(SafeFileHandle handle, out BY_HANDLE_FILE_INFORMATION lpFileInformation); | |
public static uint GetLinkCount(string filepath) | |
{ | |
using (var fs = File.OpenRead(filepath)) | |
return GetLinkCount(fs.SafeFileHandle); | |
} | |
public static uint GetLinkCount(SafeFileHandle handle) | |
{ | |
BY_HANDLE_FILE_INFORMATION info; | |
GetFileInformationByHandle(handle, out info); | |
return info.NumberOfLinks; | |
} | |
} | |
public static class MyExtensions | |
{ | |
#region Type Utility | |
public static T As<T>(this object obj) | |
where T : class | |
{ | |
return obj as T; | |
} | |
public static IEnumerable<T> AsEnumerable<T>(this object obj) | |
{ | |
return (IEnumerable<T>)obj; | |
} | |
public static object TypeInvokeMember(this object target, string name, BindingFlags invokeAttr, params object[] args) | |
{ | |
return target.GetType().InvokeMember(name, invokeAttr, null, target, args); | |
} | |
public static object InvokeMember(this System.Reflection.IReflect target, string name, BindingFlags invokeAttr, params object[] args) | |
{ | |
return target.InvokeMember(name, invokeAttr, null, target, args, null, null, null); | |
} | |
public static object InvokeMethod(this System.Reflection.IReflect target, string name, params object[] args) | |
{ | |
return target.InvokeMember(name, BindingFlags.InvokeMethod, null, target, args, null, null, null); | |
} | |
#endregion | |
#region Higher-order | |
public static T Do<T>(this T param, Action<T> pred) | |
{ | |
pred(param); | |
return param; | |
} | |
public static TResult Apply<T, TResult>(this T param, Func<T, TResult> func) | |
{ | |
return func(param); | |
} | |
public static TState FoldL<TState>(this TState init, int count, Func<TState, TState> pred) | |
{ | |
var state = init; | |
for (var i = 0; i < count; ++i) | |
state = pred(state); | |
return state; | |
} | |
#endregion | |
#region Sequence Generator | |
public static IEnumerable<TResult> Times<TResult>(this int count, Func<TResult> collector) | |
{ | |
for (var i = 0; i < count; ++i) | |
yield return collector(); | |
} | |
public static IEnumerable<T> For<T>(this T initial, Func<T, bool> condition, Func<T, T> step) | |
{ | |
for (var i = initial; condition(i); i = step(i)) | |
yield return i; | |
} | |
public static IEnumerable<int> For(this int initial, Func<int, bool> condition, int step = 1) | |
{ | |
for (var i = initial; condition(i); i += step) | |
yield return i; | |
} | |
public static IEnumerable<int> UpTo(this int initial, int max, int step = 1) | |
{ | |
for (var i = initial; i <= max; i += step) | |
yield return i; | |
} | |
public static IEnumerable<int> DownTo(this int initial, int min, int step = 1) | |
{ | |
for (var i = initial; i >= min; i -= step) | |
yield return i; | |
} | |
#endregion | |
#region String Utility | |
public static string FormatWith(this string format, object arg) | |
{ | |
return string.Format(format, arg); | |
} | |
public static string FormatWith(this string format, params object[] args) | |
{ | |
return string.Format(format, args); | |
} | |
public static IEnumerable<string> Format<T>(this IEnumerable<T> values, string format) | |
{ | |
foreach (var v in values) | |
yield return string.Format(format, v); | |
} | |
public static string JoinToString<T>(this IEnumerable<T> values, string separator) | |
{ | |
return string.Join(separator, values); | |
} | |
public static string Trunc(this string str, int maxlen) | |
{ | |
return str.Substring(0, Math.Min(str.Length, maxlen)); | |
} | |
public static string Substring(this string str, string from, string to) | |
{ | |
var pos = str.IndexOf(from) + from.Length; | |
var len = str.IndexOf(to) - pos; | |
return (pos >= 0 && len >= 0) ? str.Substring(pos, len) : null; | |
} | |
public static string ApplyAsCharArray(this string str, Func<char[], IEnumerable<char>> op) | |
{ | |
return new string(op(str.ToCharArray()).ToArray()); | |
} | |
public static string ToHexString(this ICollection<byte> bytes) | |
{ | |
var sb = new StringBuilder(bytes.Count * 2); | |
foreach (var b in bytes) | |
sb.Append(b.ToString("x2")); | |
return sb.ToString(); | |
} | |
public static IEnumerable<string>SplitByLength(this string str, int length) | |
{ | |
int i = 0; | |
for (; str.Length - i > length; i += length) | |
yield return str.Substring(i, length); | |
if (i < str.Length) | |
yield return str.Substring(i); | |
} | |
#endregion | |
#region Sequence Extension | |
public static void ForEach<T>(this IEnumerable<T> source, Action<T> pred) | |
{ | |
foreach (var item in source) | |
pred(item); | |
} | |
public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> pred) | |
{ | |
var index = 0; | |
foreach (var item in source) | |
pred(item, index++); | |
} | |
public static async Task ForEachAsync<T>(this IEnumerable<T> source, Func<T, int, Task> pred) | |
{ | |
var index = 0; | |
foreach (var item in source) | |
await pred(item, index++); | |
} | |
public static void ForEach<T>(this IEnumerable<T> source, params Action<T>[] preds) | |
{ | |
int i = 0; | |
foreach (var item in source) | |
preds[i++ % preds.Length](item); | |
} | |
public static IEnumerable<T> DoAll<T>(this IEnumerable<T> source, Action<T> pred) | |
{ | |
foreach (var item in source) | |
{ | |
pred(item); | |
yield return item; | |
} | |
} | |
public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, | |
Func<TSource> supplier) | |
{ | |
using (var e = source.GetEnumerator()) | |
{ | |
if (e.MoveNext()) | |
{ | |
do | |
{ | |
yield return e.Current; | |
} while (e.MoveNext()); | |
} | |
else | |
{ | |
yield return supplier(); | |
} | |
} | |
} | |
public static T FirstOr<T>(this IEnumerable<T> source, T defaultValue) | |
{ | |
using (var e = source.GetEnumerator()) | |
{ | |
if (e.MoveNext()) | |
{ | |
return e.Current; | |
} | |
else | |
{ | |
return defaultValue; | |
} | |
} | |
} | |
public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> condition , T defaultValue) | |
{ | |
return source.Where(condition).FirstOr(defaultValue); | |
} | |
public static IEnumerable<T> Compact<T>(this IEnumerable<T> source) | |
{ | |
return source.Where(_ => _ != null); | |
} | |
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> source, Func<T, bool> pred) | |
{ | |
return source.Where(_ => !pred(_)); | |
} | |
public static IEnumerable<T> Concat<T>(this IEnumerable<T> source, T item) | |
{ | |
return source.Concat(Enumerable.Repeat(item, 1)); | |
} | |
public static Array ToArray<T>(this IEnumerable<T> source, Type elementType) | |
{ | |
var src_array = source as Array; | |
if (src_array == null) | |
src_array = source.ToArray(); | |
var dest = Array.CreateInstance(elementType, src_array.Length); | |
Array.Copy(src_array, dest, src_array.Length); | |
return dest; | |
} | |
#endregion | |
#region Expressionized `if` | |
public static bool Then(this bool cond, Action action) | |
{ | |
if (cond) action(); | |
return cond; | |
} | |
public static bool Else(this bool cond, Action action) | |
{ | |
if (!cond) action(); | |
return cond; | |
} | |
#endregion | |
#region Encoding | |
private static Encoding DefaultEncoding { get { return Encoding.UTF8; } } | |
public static byte[] GetBytes(this string str, Encoding enc = null) | |
{ | |
enc = enc ?? DefaultEncoding; | |
return enc.GetBytes(str); | |
} | |
public static void Write(this Stream stream, string str, Encoding enc = null) | |
{ | |
enc = enc ?? DefaultEncoding; | |
var bytes = enc.GetBytes(str); | |
stream.Write(bytes, 0, bytes.Length); | |
} | |
public static async void WriteAsync(this Stream stream, string str, Encoding enc = null) | |
{ | |
enc = enc ?? DefaultEncoding; | |
var bytes = enc.GetBytes(str); | |
await stream.WriteAsync(bytes, 0, bytes.Length); | |
} | |
#endregion | |
#region Enum | |
public static bool In<T>(this T target, params T[] values) | |
{ | |
return values.Any(x => x.Equals(target)); | |
} | |
#endregion | |
#region FileDialog | |
public static string GetFilename(this FileDialog dialog) | |
=> dialog.ShowDialog() == DialogResult.OK ? dialog.FileName : null; | |
public static string[] GetFilenames(this FileDialog dialog) | |
=> dialog.ShowDialog() == DialogResult.OK ? dialog.FileNames : null; | |
public static string GetSelectedPath(this FolderBrowserDialog dialog) | |
=> dialog.ShowDialog() == DialogResult.OK ? dialog.SelectedPath : null; | |
#endregion | |
public static T DumpWithFormat<T>(this T value, string format) | |
where T : IFormattable | |
{ | |
value.ToString(format, null).Dump(); | |
return value; | |
} | |
} | |
public sealed class BinaryReaderBE : BinaryReader | |
{ | |
public BinaryReaderBE(Stream stream) : base(stream) { } | |
public BinaryReaderBE(Stream stream, Encoding encoding) : base(stream, encoding) { } | |
public BinaryReaderBE(Stream stream, Encoding encoding, bool leaveOpen) : base(stream, encoding, leaveOpen) { } | |
private byte[] buf = new byte[8]; | |
private T ReadBE<T>(Func<byte[], int, T> bitconv, int size) | |
{ | |
this.Read(buf, 0, size); | |
Array.Reverse(buf, 0, size); | |
return bitconv(buf, 0); | |
} | |
public override Int16 ReadInt16() => ReadBE(BitConverter.ToInt16, 2); | |
public override UInt16 ReadUInt16() => ReadBE(BitConverter.ToUInt16, 2); | |
public override Int32 ReadInt32() => ReadBE(BitConverter.ToInt32, 4); | |
public override UInt32 ReadUInt32() => ReadBE(BitConverter.ToUInt32, 4); | |
public override Int64 ReadInt64() => ReadBE(BitConverter.ToInt64, 8); | |
public override UInt64 ReadUInt64() => ReadBE(BitConverter.ToUInt64, 8); | |
} | |
#region Awaiter | |
public interface IAwaitable | |
{ | |
IAwaiter GetAwaiter(); | |
} | |
public interface IAwaiter : ICriticalNotifyCompletion | |
{ | |
bool IsCompleted { get; } | |
void GetResult(); | |
} | |
/// <summary> | |
/// EnumerableEx.Createの改良版 | |
/// </summary> | |
public static class EnumerableGenerator | |
{ | |
public static IEnumerable<T> Create<T>(Func<Func<T, IAwaitable>, Task> create) | |
{ | |
foreach (var x in new Yielder<T>(create)) | |
yield return x; | |
} | |
private class Yielder<T> : IAwaitable, IAwaiter, IDisposable | |
{ | |
private Action _continuation; | |
private CancellationTokenSource _cts; | |
private Task _task; | |
public Yielder(Func<Func<T, IAwaitable>, Task> create) | |
{ | |
_cts = new CancellationTokenSource(); | |
_continuation = () => | |
_task = create(v => | |
{ | |
this.Current = v; | |
return this; | |
}); | |
} | |
public IAwaiter GetAwaiter() => this; | |
public bool IsCompleted => false; | |
[System.Security.SecurityCritical] | |
public void UnsafeOnCompleted(Action continuation) { _continuation = continuation; } | |
public void OnCompleted(Action continuation) { _continuation = continuation; } | |
public void GetResult() { _cts.Token.ThrowIfCancellationRequested(); } | |
public Yielder<T> GetEnumerator() => this; | |
public T Current { get; private set; } | |
public void Reset() { throw new NotSupportedException(); } | |
public bool MoveNext() | |
{ | |
_continuation(); | |
if (_task.IsFaulted) throw _task.Exception.InnerException; | |
return !_task.IsCompleted; | |
} | |
public void Dispose() | |
{ | |
if (!_task.IsCompleted) | |
{ | |
_cts.Cancel(); | |
_continuation(); | |
} | |
_task.Dispose(); | |
} | |
} | |
} | |
/// <summary> | |
/// メソッドを一時停止する汎用クラス | |
/// </summary> | |
public class YieldState : IAwaitable, IAwaiter | |
{ | |
private Action _continuation; | |
#region IAwaitable / IAwaiter | |
IAwaiter IAwaitable.GetAwaiter() => this; | |
bool IAwaiter.IsCompleted => false; | |
void IAwaiter.GetResult() { } | |
[System.Security.SecurityCritical] | |
void ICriticalNotifyCompletion.UnsafeOnCompleted(Action continuation) { _continuation = continuation; } | |
void INotifyCompletion.OnCompleted(Action continuation) { _continuation = continuation; } | |
#endregion | |
public IAwaitable Yield() => this; | |
/// <summary> | |
/// 再開した場合はtrue、そもそも中断してなければfalseを返す。 | |
/// </summary> | |
public bool Resume() | |
{ | |
if (_continuation != null) | |
{ | |
var cont = _continuation; | |
_continuation = null; | |
cont(); | |
return true; | |
} | |
else return false; | |
} | |
} | |
#endregion | |
public static class RegexExtensions | |
{ | |
private static Func<Group, object> GetSimpleConverter(TypeConverter conv) | |
=> g => conv.ConvertFrom(g.Value); | |
private static Func<Group, object> GetArrayConverter(Type arrayType) | |
{ | |
var elemType = arrayType.GetElementType(); | |
var conv = TypeDescriptor.GetConverter(elemType); | |
return g => g.Captures.Cast<Capture>().Select(c => conv.ConvertFromString(c.Value)).ToArray(elemType); | |
} | |
public static Maybe<Match> AsMaybe(this Match match) | |
{ | |
return match.Success ? Maybe.Create(match) : new Maybe<Match>(); | |
} | |
public static T MapGroups<T>(this Match match) | |
where T : new() | |
=> Ex.Seq(match).MapGroups<T>().First(); | |
public static IEnumerable<T> MapGroups<T>(this MatchCollection matches) | |
where T : new() | |
=> matches.Cast<Match>().MapGroups<T>(); | |
public static IEnumerable<T> MapGroups<T>(this IEnumerable<Match> matches) | |
where T: new() | |
{ | |
var props = TypeDescriptor.GetProperties(typeof(T)) | |
.Cast<PropertyDescriptor>() | |
.Where(prop => !prop.IsReadOnly) | |
.Select(prop => new | |
{ | |
Name = prop.Name, | |
Descriptor = prop, | |
Type = prop.PropertyType, | |
Converter = prop.PropertyType.IsArray | |
? GetArrayConverter(prop.PropertyType) | |
: GetSimpleConverter(prop.Converter) | |
}).ToArray(); | |
foreach (Match match in matches) | |
{ | |
object obj = new T(); | |
foreach (var prop in props) | |
{ | |
var group = match.Groups[prop.Name]; | |
if (group.Success) | |
prop.Descriptor.SetValue(obj, prop.Converter(group)); | |
} | |
yield return (T)obj; | |
} | |
} | |
public static T MapGroups<T>(this Match match, T anonobj) | |
=> Ex.Seq(match).MapGroups(anonobj).First(); | |
public static IEnumerable<T> MapGroups<T>(this MatchCollection matches, T anonobj) | |
=> matches.Cast<Match>().MapGroups(anonobj); | |
public static IEnumerable<T> MapGroups<T>(this IEnumerable<Match> matches, T anonobj) | |
{ | |
var ctor = typeof(T).GetConstructors().First(); | |
var ctorParams = ( | |
from prop in TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>() | |
select new | |
{ | |
Name = prop.Name, | |
Type = prop.PropertyType, | |
Converter = prop.PropertyType.IsArray | |
? GetArrayConverter(prop.PropertyType) | |
: GetSimpleConverter(prop.Converter), | |
Default = prop.GetValue(anonobj) | |
} | |
).ToList(); | |
return matches | |
.Select(m => | |
from p in ctorParams | |
let g = m.Groups[p.Name] | |
select g.Success ? p.Converter(g) : p.Default | |
) | |
.Select(args => (T)ctor.Invoke(args.ToArray())); | |
} | |
} | |
public static class PropEq | |
{ | |
public static EqualityComparer<TObj> Create<TObj, TProp>(Func<TObj, TProp> selector) | |
=> new PropEq<TObj,TProp>(selector); | |
public static IEnumerable<TObj> Distinct<TObj, TProp>(this IEnumerable<TObj> source, Func<TObj, TProp> selector) | |
=> source.Distinct(new PropEq<TObj, TProp>(selector)); | |
} | |
public class PropEq<TObj,TProp>: EqualityComparer<TObj> | |
{ | |
private readonly Func<TObj, TProp> selector; | |
private readonly IEqualityComparer<TProp> propcomp; | |
public PropEq(Func<TObj, TProp> selector) | |
{ | |
this.selector = selector; | |
this.propcomp = EqualityComparer<TProp>.Default; | |
} | |
public override bool Equals(TObj a, TObj b) | |
=> propcomp.Equals(selector(a), selector(b)); | |
public override int GetHashCode(TObj obj) | |
=> propcomp.GetHashCode(selector(obj)); | |
} | |
// http://neue.cc/2014/09/24_479.html | |
public static class ChartExtensions | |
{ | |
/// <summary> | |
/// Create Chart control, plot items, dump! | |
/// </summary> | |
public static IEnumerable<T> DumpChart<T>(this IEnumerable<T> source, Func<T, object> xSelector, Func<T, object> ySelector, SeriesChartType chartType = SeriesChartType.Column, bool isShowXLabel = false) | |
{ | |
var chart = new Chart(); | |
chart.ChartAreas.Add(new ChartArea()); | |
var series = new Series { ChartType = chartType }; | |
foreach (var item in source) | |
{ | |
var x = xSelector(item); | |
var y = ySelector(item); | |
var index = series.Points.AddXY(x, y); | |
series.Points[index].ToolTip = item.ToString(); | |
if (isShowXLabel) series.Points[index].Label = x.ToString(); | |
} | |
chart.Series.Add(series); | |
chart.Dump("Chart"); | |
return source; | |
} | |
public static IEnumerable<IGrouping<TKey, T>> DumpGroupChart<TKey, T>(this IEnumerable<IGrouping<TKey, T>> source, Func<T, object> xSelector, Func<T, object> ySelector, SeriesChartType chartType = SeriesChartType.Line) | |
{ | |
var chart = new Chart(); | |
chart.ChartAreas.Add(new ChartArea()); | |
foreach (var g in source) | |
{ | |
var series = new Series { ChartType = chartType }; | |
foreach (var item in g) | |
{ | |
var x = xSelector(item); | |
var y = ySelector(item); | |
var index = series.Points.AddXY(x, y); | |
series.Points[index].ToolTip = item.ToString(); | |
} | |
chart.Series.Add(series); | |
} | |
chart.Dump("Chart"); | |
return source; | |
} | |
} | |
// http://qiita.com/lambdalice/items/2e47cb9960c07bf5737a | |
public static class DisposableExtensions | |
{ | |
public class Using<T> | |
where T : IDisposable | |
{ | |
public T Source { get; set; } | |
public Using(T source) | |
{ | |
Source = source; | |
} | |
} | |
/// <summary> | |
/// Introduce Select(Many) extensions for IDisposable | |
/// </summary> | |
public static Using<T> Use<T>(this T source) | |
where T : IDisposable | |
{ | |
return new Using<T>(source); | |
} | |
public static TResult SelectMany<T, TSecond, TResult> | |
(this Using<T> source, Func<T, Using<TSecond>> second, Func<T, TSecond, TResult> selector) | |
where T : IDisposable | |
where TSecond : IDisposable | |
{ | |
using (source.Source) | |
using (var s = second(source.Source).Source) | |
return selector(source.Source, s); | |
} | |
public static TResult Select<T, TResult>(this Using<T> source, Func<T, TResult> selector) | |
where T : IDisposable | |
{ | |
using (source.Source) | |
return selector(source.Source); | |
} | |
} | |
#region Monad | |
public static class Result | |
{ | |
public static ResultValue<T> Try<T>(Func<T> func) | |
{ | |
try | |
{ | |
return ResultValue<T>.GetSuccess(func()); | |
} | |
catch (Exception e) | |
{ | |
return ResultValue<T>.GetFailure(e); | |
} | |
} | |
public struct ResultValue<T> | |
{ | |
public T Result { get; private set; } | |
public Exception Exception { get; private set;} | |
public bool Success => Exception == null; | |
public static ResultValue<T> GetSuccess(T result) | |
=> new ResultValue<T> { Result = result }; | |
public static ResultValue<T> GetFailure(Exception ex) | |
=> new ResultValue<T> { Exception = ex }; | |
public TResult Match<TResult>(Func<T, TResult> mapSuccess, Func<Exception, TResult> mapFailure) | |
{ | |
return Success ? mapSuccess(Result) : mapFailure(Exception); | |
} | |
} | |
} | |
public static class Maybe | |
{ | |
public static Maybe<T> Create<T>(T value) | |
{ | |
return new Maybe<T>(value); | |
} | |
public static Maybe<T> Try<T>(Func<T> func) | |
{ | |
try | |
{ | |
return new Maybe<T>(func()); | |
} | |
catch (Exception) | |
{ | |
return new Maybe<T>(); | |
} | |
} | |
#region Extensions | |
public static Maybe<TValue> Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key) | |
{ | |
TValue val; | |
return dict.TryGetValue(key, out val) ? Maybe.Create(val) : new Maybe<TValue>(); | |
} | |
#endregion | |
} | |
public struct Maybe<T> | |
{ | |
private readonly bool _hasValue; | |
private readonly T _value; | |
public bool HasValue { get { return _hasValue; } } | |
public T Value { get { return _value; } } | |
public Maybe(T value) | |
{ | |
_value = value; | |
_hasValue = true; | |
} | |
#region TryFunc Supports | |
public delegate bool TryFunc(out T result); | |
public static Maybe<T> FromTry(TryFunc f) { T ret; return f(out ret) ? new Maybe<T>(ret) : new Maybe<T>(); } | |
public delegate bool TryFunc<T1>(T1 t1, out T result); | |
public static Maybe<T> FromTry<T1>(TryFunc<T1> f, T1 t1) { T ret; return f(t1, out ret) ? new Maybe<T>(ret) : new Maybe<T>(); } | |
#endregion | |
public Maybe<TResult> Select<TResult>(Func<T, TResult> selector) | |
{ | |
return HasValue ? Maybe.Create(selector(_value)) : new Maybe<TResult>(); | |
} | |
public TResult Match<TResult>(Func<T, TResult> just, Func<TResult> nothing) | |
{ | |
return HasValue ? just(_value) : nothing(); | |
} | |
} | |
public static class MatchExt | |
{ | |
public static MatchState<TResult> BeginMatch<TResult>(this object source) | |
{ | |
return new MatchState<TResult>(source); | |
} | |
} | |
public struct MatchState<TResult> | |
{ | |
private readonly object source; | |
private readonly Maybe<TResult> result; | |
public Maybe<TResult> Result { get { return result; } } | |
public MatchState(object source) | |
{ | |
this.source = source; | |
this.result = new Maybe<TResult>(); | |
} | |
public MatchState(object source, Maybe<TResult> result) | |
{ | |
this.source = source; | |
this.result = result; | |
} | |
public MatchState<TResult> Match<T>(Func<T, TResult> selector) | |
{ | |
if (!result.HasValue && source is T) | |
{ | |
return new MatchState<TResult>(this.source, Maybe.Create(selector((T)source))); | |
} | |
else | |
{ | |
return this; | |
} | |
} | |
} | |
#endregion | |
public abstract class DisposableBase : IDisposable | |
{ | |
private object syncRoot = new object(); | |
private bool isDisposed = false; | |
protected abstract void OnDispose(bool disposing); | |
private void Dispose(bool disposing) | |
{ | |
lock (syncRoot) | |
{ | |
if (isDisposed) return; | |
OnDispose(disposing); | |
isDisposed = true; | |
} | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
~DisposableBase() | |
{ | |
Dispose(false); | |
} | |
} | |
// http://neue.cc/2013/12/04_435.html | |
public static class TaskEnumerableExtensions | |
{ | |
public static Task WhenAll(this IEnumerable<Task> tasks) | |
{ | |
return Task.WhenAll(tasks); | |
} | |
public static Task<T[]> WhenAll<T>(this IEnumerable<Task<T>> tasks) | |
{ | |
return Task.WhenAll(tasks); | |
} | |
} | |
/// <summary> | |
/// 非公開メンバにアクセスするプロキシとして使えるDynamicObject | |
/// </summary> | |
public class NonPublicProxy : DynamicObject | |
{ | |
private static Dictionary<Type, TypeInfo> cache = new Dictionary<System.Type, NonPublicProxy.TypeInfo>(); | |
private readonly TypeInfo info; | |
private readonly object inst; | |
class TypeInfo | |
{ | |
public readonly Type Type; | |
public readonly Dictionary<string, MemberInfo> Members; | |
public TypeInfo(Type t) | |
{ | |
Type = t; | |
Members = t.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) | |
.Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property) | |
.ToDictionary(m => m.Name); | |
} | |
} | |
public static dynamic GetProxyFor(object instance) | |
{ | |
return new NonPublicProxy(instance.GetType(), instance); | |
} | |
public NonPublicProxy(Type t, object instance) | |
{ | |
if (!cache.TryGetValue(t, out info)) | |
cache[t] = info = new TypeInfo(t); | |
inst = instance; | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
MemberInfo member; | |
if (info.Members.TryGetValue(binder.Name, out member)) | |
{ | |
if (member is FieldInfo) | |
result = ((FieldInfo)member).GetValue(inst); | |
else | |
result = ((PropertyInfo)member).GetValue(inst); | |
return true; | |
} | |
else | |
{ | |
result = null; | |
return false; | |
} | |
} | |
public override bool TrySetMember(SetMemberBinder binder, object value) | |
{ | |
MemberInfo member; | |
if (info.Members.TryGetValue(binder.Name, out member)) | |
{ | |
if (member is FieldInfo) | |
((FieldInfo)member).SetValue(inst, value); | |
else | |
((PropertyInfo)member).SetValue(inst, value); | |
return true; | |
} | |
else | |
return false; | |
} | |
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) | |
{ | |
try | |
{ | |
result = info.Type.InvokeMember(binder.Name, | |
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic, | |
null, inst, args); | |
return true; | |
} | |
catch (MissingMethodException) | |
{ | |
result = null; | |
return false; | |
} | |
} | |
} | |
/// <summary> | |
/// Provides notifications when the contents of the clipboard is updated. | |
/// see http://stackoverflow.com/a/11901709/ | |
/// </summary> | |
public sealed class ClipboardListener | |
{ | |
// See http://msdn.microsoft.com/en-us/library/ms649021%28v=vs.85%29.aspx | |
private const int WM_CLIPBOARDUPDATE = 0x031D; | |
//http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only | |
private static IntPtr HWND_MESSAGE = new IntPtr(-3); | |
[DllImport("user32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool AddClipboardFormatListener(IntPtr hwnd); | |
/// <summary> | |
/// Occurs when the contents of the clipboard is updated. | |
/// </summary> | |
public static event Action ClipboardUpdate = () => { }; | |
public static IObservable<System.Reactive.Unit> ClipboardUpdateAsObservable() | |
=> Observable.FromEvent(_ => ClipboardUpdate += _, _ => ClipboardUpdate -= _); | |
private static NotificationForm _form = new NotificationForm(); | |
/// <summary> | |
/// Hidden form to recieve the WM_CLIPBOARDUPDATE message. | |
/// </summary> | |
private class NotificationForm : NativeWindow | |
{ | |
public NotificationForm() | |
{ | |
CreateHandle(new CreateParams { Parent = HWND_MESSAGE }); | |
AddClipboardFormatListener(Handle); | |
} | |
protected override void WndProc(ref Message m) | |
{ | |
if (m.Msg == WM_CLIPBOARDUPDATE) | |
{ | |
ClipboardUpdate(); | |
} | |
base.WndProc(ref m); | |
} | |
} | |
} | |
public static class MyBench | |
{ | |
public static IEnumerable<TimeSpan> Do(int count, params Action[] testcases) | |
{ | |
var sw = new Stopwatch(); | |
foreach (var testcase in testcases) | |
{ | |
sw.Restart(); | |
for (int i = 0; i < count; ++i) | |
testcase(); | |
sw.Stop(); | |
yield return sw.Elapsed; | |
} | |
} | |
} | |
public static class AssemblyExporter | |
{ | |
public static void OpenWithILSpy() | |
=> Process.Start(@"E:\onlinesoft\Programming\ILSpy\ILSpy.exe", Assembly.GetCallingAssembly().Location); | |
public enum Kind { Dll, Windows, Console } | |
public class Options | |
{ | |
public bool EmbedReferencedAssemblies { get; set; } | |
public bool EmbedLoadedAssemblies { get; set; } | |
public IEnumerable<Assembly> EmbedAssemblies { get; set;} | |
public string Namespace { get; set;} | |
public Kind Kind { get; set; } | |
} | |
private static HashSet<MethodBase> _callerOfHasExported; | |
public static bool HasExported() | |
{ | |
if(_callerOfHasExported == null) | |
_callerOfHasExported = new HashSet<MethodBase>(); | |
_callerOfHasExported.Add(new StackFrame(1).GetMethod()); | |
return false; | |
} | |
public static bool IsRunningFromLINQPad() | |
=> Type.GetType("LINQPad.Util, LINQPad") != null; | |
public static void Export(string filename) | |
{ | |
var entrypoint = new StackTrace().GetFrames() | |
.Select(f => f.GetMethod()) | |
.Last(f => f.DeclaringType.FullName == "UserQuery"); | |
var asm = Mono.Cecil.AssemblyDefinition.ReadAssembly(entrypoint.DeclaringType.Assembly.Location); | |
var userquery = asm.MainModule.GetType("UserQuery"); | |
// エントリポイントの設定 | |
// also: param == (void|string[]) && ret == (void|int) | |
var method = userquery.Methods.Where(m => m.Name == "Main" && m.IsStatic).FirstOrDefault(); | |
if (method == null) | |
{ | |
var ep_class = new Mono.Cecil.TypeDefinition("", "<EntryPoint>", Mono.Cecil.TypeAttributes.Class, asm.MainModule.TypeSystem.Object); | |
asm.MainModule.Types.Add(ep_class); | |
var ep_def = userquery.Methods.First(m => m.Name == entrypoint.Name); | |
ep_def.Attributes = ep_def.Attributes & ~Mono.Cecil.MethodAttributes.Private | Mono.Cecil.MethodAttributes.Assembly; | |
var ctor_def = userquery.Methods.First(m => m.IsConstructor && !m.HasParameters); | |
var void_t = asm.MainModule.TypeSystem.Void; | |
method = new Mono.Cecil.MethodDefinition("Main", Mono.Cecil.MethodAttributes.Static, void_t); | |
ep_class.Methods.Add(method); | |
var il = method.Body.GetILProcessor(); | |
il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, ctor_def); | |
il.Emit(Mono.Cecil.Cil.OpCodes.Call, ep_def); | |
il.Emit(Mono.Cecil.Cil.OpCodes.Ret); | |
} | |
asm.EntryPoint = method; | |
if (_callerOfHasExported != null) | |
{ | |
foreach (var m in _callerOfHasExported) | |
{ | |
// call HasExported を探してtrueで置き換える | |
} | |
} | |
asm.MainModule.Kind = Mono.Cecil.ModuleKind.Windows; | |
asm.Write(filename); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment