public static T GetBase <T>() { Type type = typeof(T); var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); for (int i = 0; i < fields.Length; i++) { ConversionAttribute attribute = fields[i].GetCustomAttribute <ConversionAttribute>(); if (attribute.Operation == ConversionOperation.Base) { return((T)fields[i].GetRawConstantValue()); } } return(default);
private static Expression ToBaseExpression(ConversionAttribute attribute, Expression value) { if (attribute.Operation == ConversionOperation.Base) { return(value); } Expression firstOperation = OperationToExpression(value, attribute.Operation, attribute.Factor, attribute.ConversionInterface); if (attribute.SecondOperation == ConversionOperation.None) { return(firstOperation); } else { return(OperationToExpression(firstOperation, attribute.SecondOperation, attribute.SecondFactor)); } }
private static Expression FromBaseExpression(ConversionAttribute attribute, Expression value) { if (attribute.Operation == ConversionOperation.Base) { return(value); } Expression secondExpression; if (attribute.SecondOperation == ConversionOperation.None) { secondExpression = value; } else { secondExpression = OperationToReverseExpression(value, attribute.SecondOperation, attribute.SecondFactor); } return(OperationToReverseExpression(secondExpression, attribute.Operation, attribute.Factor, attribute.ConversionInterface)); }
public static Func <double, T, double> GenerateConversion <T>(bool direct) { Type type = typeof(T); var valueParameter = Expression.Parameter(typeof(double), "value"); var unitParameter = Expression.Parameter(type, "unit"); var returnTarget = Expression.Label(typeof(double)); //get fields and prepare cases for switch var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); var cases = new SwitchCase[fields.Length]; for (int i = 0; i < fields.Length; i++) { ConversionAttribute attribute = fields[i].GetCustomAttribute <ConversionAttribute>(); Expression unit = Expression.Constant(Enum.ToObject(type, fields[i].GetRawConstantValue())); Expression convertor = direct ? ToBaseExpression(attribute, valueParameter) : FromBaseExpression(attribute, valueParameter); var returnStatement = Expression.Return(returnTarget, convertor); cases[i] = Expression.SwitchCase(returnStatement, new Expression[] { unit }); } //prepare default method throwing exception var constructorInfo = typeof(ArgumentException).GetConstructor(new Type[] { typeof(string), typeof(string) }); var argumentException = Expression.New(constructorInfo, new Expression[] { Expression.Constant("Unknown unit"), Expression.Constant("unit") }); var defaultBody = Expression.Throw(argumentException); //switch statement var switchStmt = Expression.Switch(unitParameter, defaultBody, cases); //method body var body = Expression.Block(typeof(double), new Expression[] { switchStmt, Expression.Label(returnTarget, Expression.Constant(0.0)) }); //function var expression = Expression.Lambda(typeof(Func <double, T, double>), body, new ParameterExpression[] { valueParameter, unitParameter }); var functionDelegate = expression.Compile(); return((Func <double, T, double>)functionDelegate); }