Example #1
0
        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);
        }
Example #3
0
 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;
 }
Example #4
0
        /// <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));
        }
Example #5
0
 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);
     }
 }
Example #6
0
 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);
     }
 }
Example #7
0
        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);
        }
Example #8
0
        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));
        }
Example #9
0
        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);
        }
Example #10
0
        /// <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.");
        }