public override void Bind(UnitType candidate) { UnitType L = Lhs.Unit; UnitType R = Rhs.Unit; if ((L != null) && (R != null)) { // result = unitL * unitR (definition) // E.g.: Joule = Newton * Meter // Newton.cs (or Meter.cs): // public static Joule operator *(Newton lhs, Meter rhs) { return new Joule(lhs.Value * rhs.Value); } // public static Joule operator *(Meter lhs, Newton rhs) { return new Joule(lhs.Value * rhs.Value); } L.AddOuterOperation(candidate, Operation, L, R); if (L.Name != R.Name) { L.AddOuterOperation(candidate, Operation, R, L); } // => result / unitL = unitR // => result / unitR = unitL // // Joule.cs: // public static Newton operator /(Joule lhs, Meter rhs) { return new Newton(lhs.Value / rhs.Value); } // public static Meter operator /(Joule lhs, Newton rhs) { return new Meter(lhs.Value / rhs.Value); } candidate.AddOuterOperation(R, "/", candidate, L); if (L.Name != R.Name) { candidate.AddOuterOperation(L, "/", candidate, R); } } else if ((L != null) && (Rhs.IsNumeric)) { // result = unit * number (conversion) // // E.g. Centimeter = Meter * 100.0 // Meter.cs: // public static explicit operator Meter(Centimeter q) { return new Meter((Meter.Factor / Centimeter.Factor) * q.Value); } // Centimeter.cs: // public static explicit operator Centimeter(Meter q) { return new Centimeter((Centimeter.Factor / Meter.Factor) * q.Value); } // Lhs.Bind(candidate); } else if ((Lhs.IsNumeric) && (R != null)) { // result = number * unit (conversion) // E.g. Centimeter = 100.0 * Meter // Meter.cs: // public static explicit operator Meter(Centimeter q) { return new Meter((Meter.Factor / Centimeter.Factor) * q.Value); } // Centimeter.cs: // public static explicit operator Centimeter(Meter q) { return new Centimeter((Centimeter.Factor / Meter.Factor) * q.Value); } // Rhs.Bind(candidate); } }
public override void Bind(UnitType candidate) { UnitType L = Lhs.Unit; UnitType R = Rhs.Unit; if ((L != null) && (R != null)) { // result = unitL / unitR (definition) // Quotient of the same unit is always included in the list of outer operations, // so we have to avoid to enroll it twice: if (String.Equals(L.Name, R.Name)) { return; } // E.g.: MPH = Mile / Hour // Mile.cs (or Hour.cs): // public static MPH operator *(Mile lhs, Hour rhs) { return new MPH(lhs.Value / rhs.Value); } L.AddOuterOperation(candidate, "/", L, R); // => unitL / result = unitR // Mile.cs (or MPH.cs): // public static Hour operator /(Mile lhs, MPH rhs) { return new Hour(lhs.Value / rhs.Value); } L.AddOuterOperation(R, "/", L, candidate); // => result * unitR = unitL // Hour.cs (or MPH.cs): // public static Mile operator *(MPH lhs, Hour rhs) { return new Mile(lhs.Value / rhs.Value); } candidate.AddOuterOperation(L, "*", candidate, R); candidate.AddOuterOperation(L, "*", R, candidate); } else if ((L != null) && (Rhs.IsNumeric)) { // result = unit / real (conversion) // // E.g. Meter = Centimeter / 100.0 // Meter.cs: // public static explicit operator Meter(Centimeter q) { return new Meter((Meter.Factor / Centimeter.Factor) * q.Value); } // Centimeter.cs: // public static explicit operator Centimeter(Meter q) { return new Centimeter((Centimeter.Factor / Meter.Factor) * q.Value); } // Lhs.Bind(candidate); } else if ((Lhs.IsNumeric) && (R != null)) { // result = real / unit (definition) NumericType numType = R.Factor.Value.Type; // E.g. Hertz "Hz" = 1.0 / Second // Second.cs // public static Hertz operator /(double lhs, Second rhs) { return new Hertz(lhs / rhs.Value); } R.AddOuterOperation(candidate, "/", numType, R); // Hertz.cs // public static Second operator /(double lhs, Hertz rhs) { return new Second(lhs / rhs.Value); } candidate.AddOuterOperation(R, "/", numType, candidate); // Hertz.cs (or Second.cs) // public static double operator *(Hertz lhs, Second rhs) { return lhs.Value * rhs.Value; } // public static double operator *(Second lhs, Hertz rhs) { return lhs.Value * rhs.Value; } candidate.AddOuterOperation(numType, "*", candidate, R); candidate.AddOuterOperation(numType, "*", R, candidate); } }