private Union CreateUnion(Type t) { Union u = new Union(); u.TagReader = FSharpFunc <object, int> .ToConverter(FSharpValue.PreComputeUnionTagReader(t, null)); u.Cases = new List <UnionCase>(); UnionCaseInfo[] cases = FSharpType.GetUnionCases(t, null); foreach (UnionCaseInfo unionCaseInfo in cases) { UnionCase unionCase = new UnionCase(); unionCase.Tag = unionCaseInfo.Tag; unionCase.Name = unionCaseInfo.Name; unionCase.Fields = unionCaseInfo.GetFields(); unionCase.FieldReader = FSharpFunc <object, object[]> .ToConverter(FSharpValue.PreComputeUnionReader(unionCaseInfo, null)); unionCase.Constructor = FSharpFunc <object[], object> .ToConverter(FSharpValue.PreComputeUnionConstructor(unionCaseInfo, null)); u.Cases.Add(unionCase); } return(u); }
private Union CreateUnion(Type t) { Union u = new Union(); u.TagReader = (s) => FSharpValue.PreComputeUnionTagReader(t, null).Invoke(s); u.Cases = new List <UnionCase>(); UnionCaseInfo[] cases = FSharpType.GetUnionCases(t, null); foreach (UnionCaseInfo unionCaseInfo in cases) { UnionCase unionCase = new UnionCase(); unionCase.Tag = unionCaseInfo.Tag; unionCase.Name = unionCaseInfo.Name; unionCase.Fields = unionCaseInfo.GetFields(); unionCase.FieldReader = (s) => FSharpValue.PreComputeUnionReader(unionCaseInfo, null).Invoke(s); unionCase.Constructor = (s) => FSharpValue.PreComputeUnionConstructor(unionCaseInfo, null).Invoke(s); u.Cases.Add(unionCase); } return(u); }
public StringUnionConverter(UnionCaseInfo[] cases) { _readers = cases .Select(p => (p.Name, (Converter <object[], object>)FSharpValue.PreComputeUnionConstructor(p, FSharpOption <BindingFlags> .None))) .ToArray(); _tagReader = FSharpValue.PreComputeUnionTagReader(typeof(T), FSharpOption <BindingFlags> .None); _nameByTag = cases.ToDictionary(p => p.Tag, p => p.Name); //_cases = cases; }
/// <summary> /// Creates a modified copy of the original object. /// </summary> /// <typeparam name = "T"></typeparam> /// <typeparam name = "TProperty">The type of the property.</typeparam> /// <param name = "record">The record.</param> /// <param name = "property">Name of the property.</param> /// <param name = "value">The value.</param> /// <returns></returns> static T CreateModifiedCopy <T, TProperty>(T record, PropertyInfo property, TProperty value) { var originalValues = FSharpType.GetRecordFields(typeof(T), null) .Select(p => new{ X = p, Y = FSharpValue.GetRecordField(record, p) }); var values = originalValues .Select(t => t.X == property ? value : t.Y) .ToArray(); return((T)FSharpValue.MakeRecord(typeof(T), values, FSharpOption <BindingFlags> .None)); }
public ErasedUnionConverter(UnionCaseInfo info, PropertyInfo[] props) { _props = props; _isSingleValue = IsSingleValueCase(props); _isTupleValue = IsTupleCase(props); _toCase = FSharpValue.PreComputeUnionConstructor(info, FSharpOption <BindingFlags> .None); _fromCase = FSharpValue.PreComputeUnionReader(info, FSharpOption <BindingFlags> .None); if (_isTupleValue) { _tupleType = MakeTupleType(props); _toTuple = FSharpValue.PreComputeTupleConstructor(_tupleType); _fromTuple = FSharpValue.PreComputeTupleReader(_tupleType); } }
public CaseData(UnionCaseInfo info, PropertyInfo[] props) { Name = info.Name; Props = props; ToCase = FSharpValue.PreComputeUnionConstructor(info, FSharpOption <BindingFlags> .None); FromCase = FSharpValue.PreComputeUnionReader(info, FSharpOption <BindingFlags> .None); IsEmpty = props.Length == 0; IsSingleCase = IsSingleValueCase(props); if (IsTupleCase(props)) { TupleType = MakeTupleType(props); ToTuple = FSharpValue.PreComputeTupleConstructor(TupleType); FromTuple = FSharpValue.PreComputeTupleReader(TupleType); } }
public void TupleToListTimed() { object tup = Tupler.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20); Timer.Action1 = () => Tupler.ToList(tup); Timer.Action2 = () => FSharpValue.GetTupleFields(tup).ToList(); var elapsed = Timer.Go(50000); Console.WriteLine("Impromptu: " + elapsed.Item1); Console.WriteLine("FSharp Refelection: " + elapsed.Item2); Console.WriteLine("Impromptu VS FSharp Reflection: {0}", TimeIt.RelativeSpeed(elapsed)); Assert.Less(elapsed.Item1, elapsed.Item2); }
public static FilterContainer GenerateEqualityFilter <T>(this Expression expression) where T : class { var binaryExpression = expression as BinaryExpression; var value = GetValue(binaryExpression.Right); if (FSharpType.IsUnion(value.GetType(), FSharpOption <BindingFlags> .None)) { var fields = FSharpValue.GetUnionFields(value, value.GetType(), FSharpOption <BindingFlags> .None); var unionCase = fields.Item1; value = unionCase.Name; } var filterDescriptor = new FilterDescriptor <T>(); var fieldName = GetFieldName(binaryExpression.Left); return(filterDescriptor.Term(fieldName, value)); }
public void ListToTupleTimed() { var list = new object[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; Timer.Action1 = () => Tupler.ToTuple(list); Timer.Action2 = () => { var types = list.Select(it => it.GetType()).ToArray(); var tupType = FSharpType.MakeTupleType(types); FSharpValue.MakeTuple(list, tupType); }; var elapsed = Timer.Go(50000); Console.WriteLine("Impromptu: " + elapsed.Item1); Console.WriteLine("FSharp Refelection: " + elapsed.Item2); Console.WriteLine("Impromptu VS FSharp Reflection: {0}", TimeIt.RelativeSpeed(elapsed)); Assert.Less(elapsed.Item1, elapsed.Item2); }
/// <summary> /// Type情報からデフォルトのインスタンスを生成する. /// </summary> /// <param name="type">デフォルトインスタンスを生成したいType情報</param> /// <returns>Type情報から生成したインスタンス</returns> public static object MakeDefault(this Type type) { var none = FSharpOption <BindingFlags> .None; if (type == typeof(int)) { return(default(int)); } if (type == typeof(uint)) { return(default(uint)); } if (type == typeof(short)) { return(default(short)); } if (type == typeof(ushort)) { return(default(ushort)); } if (type == typeof(long)) { return(default(long)); } if (type == typeof(ulong)) { return(default(ulong)); } if (type == typeof(byte)) { return(default(byte)); } if (type == typeof(sbyte)) { return(default(sbyte)); } if (type == typeof(bool)) { return(default(bool)); } if (type == typeof(float)) { return(default(float)); } if (type == typeof(double)) { return(default(double)); } if (type == typeof(decimal)) { return(default(decimal)); } if (type == typeof(char)) { return(default(char)); } if (type == typeof(string)) { return(default(string)); } if (type == typeof(Guid)) { return(default(Guid)); } if (type == typeof(DateTime)) { return(default(DateTime)); } if (type == typeof(DateTimeOffset)) { return(default(DateTimeOffset)); } if (type == typeof(byte[])) { return(default(byte[])); } if (type == typeof(int?)) { return(default(int?)); } if (type == typeof(uint?)) { return(default(uint?)); } if (type == typeof(short?)) { return(default(short?)); } if (type == typeof(ushort?)) { return(default(ushort?)); } if (type == typeof(long?)) { return(default(long?)); } if (type == typeof(ulong?)) { return(default(ulong?)); } if (type == typeof(byte?)) { return(default(byte?)); } if (type == typeof(sbyte?)) { return(default(sbyte?)); } if (type == typeof(bool?)) { return(default(bool?)); } if (type == typeof(float?)) { return(default(float?)); } if (type == typeof(double?)) { return(default(double?)); } if (type == typeof(decimal?)) { return(default(decimal?)); } if (type == typeof(char?)) { return(default(char?)); } if (type == typeof(Guid?)) { return(default(Guid?)); } if (type == typeof(DateTime?)) { return(default(DateTime?)); } if (type == typeof(DateTimeOffset?)) { return(default(DateTimeOffset?)); } if (type == typeof(FSharpOption <int>)) { return(FSharpOption <int> .None); } if (type == typeof(FSharpOption <uint>)) { return(FSharpOption <uint> .None); } if (type == typeof(FSharpOption <short>)) { return(FSharpOption <short> .None); } if (type == typeof(FSharpOption <ushort>)) { return(FSharpOption <ushort> .None); } if (type == typeof(FSharpOption <long>)) { return(FSharpOption <long> .None); } if (type == typeof(FSharpOption <ulong>)) { return(FSharpOption <ulong> .None); } if (type == typeof(FSharpOption <byte>)) { return(FSharpOption <byte> .None); } if (type == typeof(FSharpOption <sbyte>)) { return(FSharpOption <sbyte> .None); } if (type == typeof(FSharpOption <bool>)) { return(FSharpOption <bool> .None); } if (type == typeof(FSharpOption <float>)) { return(FSharpOption <float> .None); } if (type == typeof(FSharpOption <double>)) { return(FSharpOption <double> .None); } if (type == typeof(FSharpOption <decimal>)) { return(FSharpOption <decimal> .None); } if (type == typeof(FSharpOption <char>)) { return(FSharpOption <char> .None); } if (type == typeof(FSharpOption <string>)) { return(FSharpOption <string> .None); } if (type == typeof(FSharpOption <Guid>)) { return(FSharpOption <Guid> .None); } if (type == typeof(FSharpOption <DateTime>)) { return(FSharpOption <DateTime> .None); } if (type == typeof(FSharpOption <DateTimeOffset>)) { return(FSharpOption <DateTimeOffset> .None); } if (type == typeof(FSharpOption <byte[]>)) { return(FSharpOption <byte[]> .None); } // Option型(F#) // - FSharpType.IsUnion()でも引っ掛かってしまうので、 // それよりも前に判定をする必要がある. if (type.IsFsharpOption()) { return(type .GetProperty("None", BindingFlags.Public | BindingFlags.Static) .GetGetMethod() .Invoke(null, null)); } // 判別共用体(F#) if (type.IsFsharpDiscriminatedUnions()) { var ctor = FSharpType.GetUnionCases(type, none).FirstOrDefault(); if (ctor == null) { throw new Exception("Invalid discriminated-unions."); } var ps = ctor.GetFields(); var qs = new object[ps.Length]; for (var i = 0; i < ps.Length; i++) { qs[i] = ps[i].PropertyType.MakeDefault(); } return(FSharpValue.MakeUnion(ctor, qs, none)); } // 列挙型 if (type.IsEnum) { return(type.GetEnumValue(0)); } // 構造体 if (type.IsValueType) { return(Activator.CreateInstance(type)); } // クラス if (type.IsClass) { var ctor = type.GetConstructors().FirstOrDefault(); // publicコンストラクタが存在しない場合、nullを返す if (ctor is null) { return(null); } else { var ps = ctor.GetParameters(); var qs = new object[ps.Length]; for (int i = 0; i < ps.Length; i++) { qs[i] = ps[i].ParameterType.MakeDefault(); } #if NET40 || NET45 || NET46 || NET472 || NET48 || NETCOREAPP3_1 || NET5_0 return(type.Constructor(qs)); #else return(Activator.CreateInstance(type, qs)); #endif } } throw new ArgumentException("'type' is not supported."); }
public object Resolve(Type memberType, object value) { var none = FSharpOption <BindingFlags> .None; if (memberType == typeof(int)) { return(value is DBNull ? default(int) : value); } if (memberType == typeof(uint)) { return(value is DBNull ? default(uint) : value); } if (memberType == typeof(short)) { return(value is DBNull ? default(short) : value); } if (memberType == typeof(ushort)) { return(value is DBNull ? default(ushort) : value); } if (memberType == typeof(long)) { return(value is DBNull ? default(long) : value); } if (memberType == typeof(ulong)) { return(value is DBNull ? default(ulong) : value); } if (memberType == typeof(byte)) { return(value is DBNull ? default(byte) : value); } if (memberType == typeof(sbyte)) { return(value is DBNull ? default(sbyte) : value); } if (memberType == typeof(bool)) { return(value is DBNull ? default(bool) : value); } if (memberType == typeof(float)) { return(value is DBNull ? default(float) : value); } if (memberType == typeof(double)) { return(value is DBNull ? default(double) : value); } if (memberType == typeof(decimal)) { return(value is DBNull ? default(decimal) : value); } if (memberType == typeof(char)) { return(value is DBNull ? default(char) : value); } if (memberType == typeof(string)) { return(value is DBNull ? default(string) : value); } if (memberType == typeof(Guid)) { return(value is DBNull ? default(Guid) : value); } if (memberType == typeof(DateTime)) { return(value is DBNull ? default(DateTime) : value); } if (memberType == typeof(DateTimeOffset)) { return(value is DBNull ? default(DateTimeOffset) : value); } if (memberType == typeof(byte[])) { return(value); } if (memberType == typeof(int?)) { return(value is DBNull ? default(int?) : value); } if (memberType == typeof(uint?)) { return(value is DBNull ? default(uint?) : value); } if (memberType == typeof(short?)) { return(value is DBNull ? default(short?) : value); } if (memberType == typeof(ushort?)) { return(value is DBNull ? default(ushort?) : value); } if (memberType == typeof(long?)) { return(value is DBNull ? default(long?) : value); } if (memberType == typeof(ulong?)) { return(value is DBNull ? default(ulong?) : value); } if (memberType == typeof(byte?)) { return(value is DBNull ? default(byte?) : value); } if (memberType == typeof(sbyte?)) { return(value is DBNull ? default(sbyte?) : value); } if (memberType == typeof(bool?)) { return(value is DBNull ? default(bool?) : value); } if (memberType == typeof(float?)) { return(value is DBNull ? default(float?) : value); } if (memberType == typeof(double?)) { return(value is DBNull ? default(double?) : value); } if (memberType == typeof(decimal?)) { return(value is DBNull ? default(decimal?) : value); } if (memberType == typeof(char?)) { return(value is DBNull ? default(char?) : value); } if (memberType == typeof(Guid?)) { return(value is DBNull ? default(Guid?) : value); } if (memberType == typeof(DateTime?)) { return(value is DBNull ? default(DateTime?) : value); } if (memberType == typeof(DateTimeOffset?)) { return(value is DBNull ? default(DateTimeOffset?) : value); } if (memberType == typeof(FSharpOption <int>)) { return(value is DBNull ? FSharpOption <int> .None : FSharpOption <int> .Some((int)value)); } if (memberType == typeof(FSharpOption <uint>)) { return(value is DBNull ? FSharpOption <uint> .None : FSharpOption <uint> .Some((uint)value)); } if (memberType == typeof(FSharpOption <short>)) { return(value is DBNull ? FSharpOption <short> .None : FSharpOption <short> .Some((short)value)); } if (memberType == typeof(FSharpOption <ushort>)) { return(value is DBNull ? FSharpOption <ushort> .None : FSharpOption <ushort> .Some((ushort)value)); } if (memberType == typeof(FSharpOption <long>)) { return(value is DBNull ? FSharpOption <long> .None : FSharpOption <long> .Some((long)value)); } if (memberType == typeof(FSharpOption <ulong>)) { return(value is DBNull ? FSharpOption <ulong> .None : FSharpOption <ulong> .Some((ulong)value)); } if (memberType == typeof(FSharpOption <byte>)) { return(value is DBNull ? FSharpOption <byte> .None : FSharpOption <byte> .Some((byte)value)); } if (memberType == typeof(FSharpOption <sbyte>)) { return(value is DBNull ? FSharpOption <sbyte> .None : FSharpOption <sbyte> .Some((sbyte)value)); } if (memberType == typeof(FSharpOption <bool>)) { return(value is DBNull ? FSharpOption <bool> .None : FSharpOption <bool> .Some((bool)value)); } if (memberType == typeof(FSharpOption <float>)) { return(value is DBNull ? FSharpOption <float> .None : FSharpOption <float> .Some((float)value)); } if (memberType == typeof(FSharpOption <double>)) { return(value is DBNull ? FSharpOption <double> .None : FSharpOption <double> .Some((double)value)); } if (memberType == typeof(FSharpOption <decimal>)) { return(value is DBNull ? FSharpOption <decimal> .None : FSharpOption <decimal> .Some((decimal)value)); } if (memberType == typeof(FSharpOption <char>)) { return(value is DBNull ? FSharpOption <char> .None : FSharpOption <char> .Some((char)value)); } if (memberType == typeof(FSharpOption <string>)) { return(value is DBNull ? FSharpOption <string> .None : FSharpOption <string> .Some((string)value)); } if (memberType == typeof(FSharpOption <Guid>)) { return(value is DBNull ? FSharpOption <Guid> .None : FSharpOption <Guid> .Some((Guid)value)); } if (memberType == typeof(FSharpOption <DateTime>)) { return(value is DBNull ? FSharpOption <DateTime> .None : FSharpOption <DateTime> .Some((DateTime)value)); } if (memberType == typeof(FSharpOption <DateTimeOffset>)) { return(value is DBNull ? FSharpOption <DateTimeOffset> .None : FSharpOption <DateTimeOffset> .Some((DateTimeOffset)value)); } if (memberType == typeof(FSharpOption <byte[]>)) { return(value is DBNull ? FSharpOption <byte[]> .None : FSharpOption <byte[]> .Some((byte[])value)); } // optional values (F#) if (memberType.IsGenericType && !memberType.IsGenericTypeDefinition && !memberType.IsGenericParameter && typeof(FSharpOption <>) == memberType.GetGenericTypeDefinition()) { if (value is DBNull) { return(memberType.GetProperty("None", BindingFlags.Public | BindingFlags.Static).GetGetMethod().Invoke(null, null)); } var genericTypes = memberType.GetGenericArguments(); if (genericTypes.Length != 1) { throw new Exception("Invalid fsharp option value."); } var genericType = genericTypes[0]; return(memberType.GetMethod("Some", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { Resolve(genericType, value) })); } // discriminated unions (F#) if (FSharpType.IsUnion(memberType, none)) { var ctor = FSharpType.GetUnionCases(memberType, none).FirstOrDefault(cinfo => cinfo.GetFields().Length == 1); if (ctor == null) { throw new Exception("Invalid discriminated-unions."); } var field = ctor.GetFields()[0]; return(FSharpValue.MakeUnion(ctor, new object[] { Resolve(field.PropertyType, value) }, none)); } // nullable values if (memberType.IsGenericType && !memberType.IsGenericTypeDefinition && !memberType.IsGenericParameter && typeof(Nullable <>) == memberType.GetGenericTypeDefinition()) { return(value is DBNull ? null : value); } // non nullable values if (memberType.IsValueType) { return(value is DBNull?Activator.CreateInstance(memberType) : value); } // class values if (memberType.IsClass) { if (value is string) { return(value); } return(value is DBNull ? null : Activator.CreateInstance(memberType, value)); } // enums if (memberType.IsEnum) { if (value is DBNull) { return(memberType.GetEnumValue(0)); } if (value is short s) { return(memberType.GetEnumValue(s)); } if (value is int i) { return(memberType.GetEnumValue(i)); } if (value is long l) { return(memberType.GetEnumValue(l)); } if (value is ushort us) { return(memberType.GetEnumValue(us)); } if (value is uint ui) { return(memberType.GetEnumValue(ui)); } if (value is ulong ul) { return(memberType.GetEnumValue(ul)); } if (value is byte b) { return(memberType.GetEnumValue(b)); } if (value is sbyte sb) { return(memberType.GetEnumValue(sb)); } } throw new Exception("Could not resolve the value."); }