StaticOperatorProxy.cs

79 lines | 2.829 kB Blame History Raw Download
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Linq.Expressions;

namespace ExpressionOperatorProxy.Generic.MathOperatorProxy
{

    /// <summary>
    /// Пример реализации взят с
    /// http://www.cyberforum.ru/csharp-net/thread1994108.html
    /// 
    /// Позволяет производить арифметические операции над Generic T типом
    /// Возможны ошибки, если используемый тип не реализует используемую операцию
    /// Список операций можно расширить на основе возможностей класса Expression
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class StaticOperatorProxy<T>
    {
        private readonly static Func<T, T, T> _addOperator;
        private readonly static Func<T, T, T> _subtractOperator;
        private readonly static Func<T, T, T> _multiplyOperator;
        private readonly static Func<T, T, T> _divideOperator;

        private static Func<T, T, T> CreateDelegate(BinaryExpression expression, ParameterExpression parameter1, ParameterExpression parameter2)
        {
            return Expression
                .Lambda<Func<T, T, T>>(
                    expression,
                    new[]
                    {
                        parameter1,
                        parameter2
                    }
                ).Compile();
        }

        static StaticOperatorProxy()
        {

            var operand1 = Expression.Parameter(typeof(T), "o1");
            var operand2 = Expression.Parameter(typeof(T), "o2");

            var addCall = Expression.Add(operand1, operand2);
            var subtractCall = Expression.Subtract(operand1, operand2);
            var multiplyCall = Expression.Multiply(operand1, operand2);
            var dividetractCall = Expression.Divide(operand1, operand2);

            _addOperator = CreateDelegate(addCall, operand1, operand2);
            _subtractOperator = CreateDelegate(subtractCall, operand1, operand2);
            _multiplyOperator = CreateDelegate(multiplyCall, operand1, operand2);
            _divideOperator = CreateDelegate(dividetractCall, operand1, operand2);
        }


        public static T Add(T operand1, T operand2)
        {
            return _addOperator(operand1, operand2);
        }
        public static T Subtract(T operand1, T operand2)
        {
            return _subtractOperator(operand1, operand2);
        }
        public static T Multiply(T operand1, T operand2)
        {
            return _multiplyOperator(operand1, operand2);
        }
        public static T Divide(T operand1, T operand2)
        {
            return _divideOperator(operand1, operand2);
        }

    }
}