Note: This only works in .NET 4 Framework. Other users, excuse me.
For doing simple arithmatic operations between two objects, we need to
overload the operator (+,-,* etc)
. Also, we need to specify a particular type as the argument in the operator methods. Even a generic operator method is not possible or a very tough task.
So
how can we have a parent class which has all the necessary things for doing arithmetic operations and just by inheriting it, any type of child can be subject to arithmetic operations. The flexibility comes from the Microsoft DLR class
DynamicObject
.
This demo includes a class
inherited
from
DynamicObject
which has the arithmetic operations defined. Which in turn
inherited by child classes
and these child classes can perform arithmetic operations among themselves
without any operator overloading methods
.
The demo uses two specific namespaces
System.Dynamic and System.Linq.Expressions
. However all the expressions from the
linq.Expressions
may not be available with the Dynamic object, but most of the common binary operations available in C# are possible.
The parent class code is as follows:
public class CommonArithmaticObject:DynamicObject
{
protected Dictionary<string,> dictionary = new Dictionary<string,>();
public string ErrorMessage { get; set; }
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
return dictionary.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
public override bool TryBinaryOperation( BinaryOperationBinder binder, object arg, out object result)
{
CommonArithmaticObject obj;
double resultValue;
if(arg is CommonArithmaticObject)
{
obj=(CommonArithmaticObject)arg;
}else
{
result = null;
return false;
}
double dummy;
if (obj.dictionary.ContainsKey("Numeric")==false || obj.dictionary["Numeric"] == null)
{
obj.dictionary["Numeric"] = 0;
}
else if (double.TryParse(obj.dictionary["Numeric"].ToString(),out dummy)==false)
{
obj.dictionary["Numeric"] = 0;
}
if (dictionary.ContainsKey("Numeric") == false || dictionary["Numeric"] == null)
{
dictionary["Numeric"] = 0;
}
else if (double.TryParse(dictionary["Numeric"].ToString(), out dummy) == false)
{
dictionary["Numeric"] = 0;
}
try
{
switch (binder.Operation)
{
case ExpressionType.Add:
resultValue =
Convert.ToDouble(dictionary["Numeric"]) +
Convert.ToDouble(obj.dictionary["Numeric"]);
break;
case ExpressionType.Subtract:
resultValue =
Convert.ToDouble(dictionary["Numeric"]) -
Convert.ToDouble(obj.dictionary["Numeric"]);
break;
case ExpressionType.Multiply:
resultValue =
Convert.ToDouble(dictionary["Numeric"]) *
Convert.ToDouble(obj.dictionary["Numeric"]);
break;
case ExpressionType.Divide:
resultValue =
Convert.ToDouble(dictionary["Numeric"]) /
Convert.ToDouble(obj.dictionary["Numeric"]);
break;
default:
result = null;
return false;
}
}
catch(Exception e)
{
ErrorMessage = e.Message+" "+ e.InnerException !=null ? e.InnerException.Message:"";
result = null;
return false;
}
dynamic finalResult = new CommonArithmaticObject();
finalResult.Numeric = resultValue;
result = finalResult;
return true;
}
}
The following classes inherit the above Arithmetic dynamic class.
public class Maths : CommonArithmaticObject
{
private double _marksScored = 0;
public double MarksScored
{
get { return this._marksScored; }
set { this._marksScored = value; dictionary.Add("Numeric", MarksScored); }
}
}
public class Science : CommonArithmaticObject
{
private double _marksScored = 0;
public double MarksScored
{
get { return this._marksScored; }
set { this._marksScored = value; dictionary.Add("Numeric", MarksScored); }
}
}
public class Language : CommonArithmaticObject
{
private double _marksScored = 0;
public double MarksScored
{
get { return this._marksScored; }
set { this._marksScored = value; dictionary.Add("Numeric", MarksScored); }
}
}
Now these child classes can perform the defined arithmetic operations among themselves. For example...
dynamic maths = new Maths();
maths.MarksScored = 95;
dynamic science = new Science();
science.MarksScored = 87.65;
dynamic language = new Language();
language.MarksScored = 90;
dynamic totalMarks = maths + science + language;
MessageBox.Show(totalMarks.Numeric.ToString());
dynamic totalExceptLanguage = totalMarks - language;
MessageBox.Show(totalExceptLanguage.Numeric.ToString());
That is it, we are dynamic now. Cheers.