Beispiel #1
0
        private InitExpressionResult <Func <T, T, T> > CreateCoalesceWith(
            ConstructorInfo constructor)
        {
            var readableProperties = new List <PropertyInfo>(
                from p in typeof(T).GetRuntimeProperties()
                where p.CanRead
                select p);

            var readonlyProperties = new HashSet <PropertyInfo>(
                from p in readableProperties
                where false == p.CanWrite
                select p);

            var settableProperties = new HashSet <PropertyInfo>(
                from p in readableProperties
                where p.CanWrite
                select p);

            ParameterExpression left  = Parameter(typeof(T), nameof(left));
            ParameterExpression right = Parameter(typeof(T), nameof(right));

            var arguments = new List <Expression>();

            foreach (ParameterInfo parameter in constructor.GetParameters())
            {
                PropertyInfo property =
                    PickParameterMatch(readonlyProperties, parameter) ??
                    PickParameterMatch(settableProperties, parameter);

                if (property == null)
                {
                    InitExpressionError error =
                        GetNoPropertyMatchesParameterError(
                            constructor, parameter);
                    return(InitExpressionResult <Func <T, T, T> > .WithError(error));
                }

                arguments.Add(CoalesceOrMemberAccess(property, left, right));
            }

            if (readonlyProperties.Any())
            {
                InitExpressionError error =
                    GetPropertyCannotBeSetError(
                        constructor, readonlyProperties);
                return(InitExpressionResult <Func <T, T, T> > .WithError(error));
            }

            MemberInitExpression memberInitExpression = MemberInit(
                New(constructor, arguments),
                from property in settableProperties
                select Bind(
                    property,
                    CoalesceOrMemberAccess(property, left, right)));

            Expression <Func <T, T, T> > lambdaExpression =
                Lambda <Func <T, T, T> >(memberInitExpression, left, right);

            return(new InitExpressionResult <Func <T, T, T> >(lambdaExpression));
        }
Beispiel #2
0
        private static Func <TModel, TModel, TModel> BuildImplementor()
        {
            var factory = new InitExpressionFactory <TModel>();
            InitExpressionResult <Func <TModel, TModel, TModel> > result =
                factory.CreateCoalesce();

            return((newValue, lastValue) =>
            {
                var coalescable = newValue as ICoalescable <TModel>;
                if (coalescable != null)
                {
                    return coalescable.Coalesce(lastValue);
                }

                if (false == result.IsSuccess)
                {
                    var message = string.Join(
                        Environment.NewLine,
                        from error in result.Errors
                        select error.GetExceptionMessage());
                    throw new InvalidOperationException(message);
                }

                return result.Function.Invoke(newValue, lastValue);
            });
        }
Beispiel #3
0
        public InitExpressionResult <Func <T, T, T> > CreateCoalesce()
        {
            IEnumerable <ConstructorInfo> constructors =
                typeof(T).GetTypeInfo().DeclaredConstructors;

            var results = new List <InitExpressionResult <Func <T, T, T> > >(
                from constructor in constructors
                orderby constructor.GetParameters().Length descending
                select CreateCoalesceWith(constructor));

            return(results.FirstOrDefault(r => r.IsSuccess)
                   ?? InitExpressionResult <Func <T, T, T> > .WithErrors(
                       from r in results
                       from e in r.Errors
                       select e));
        }