I'm writing code using a legacy API whose code I cannot change. There is a family of methods for supported datatypes (int, double, bool, string, APIObject) to do an operation in the API. These take a parameter of the same datatype as indicated in the name of the method. Sample usages as given below
GetIntExp(5)
GetStringExp("Hello")
GetDoubleExp(1.2)
GetDateExp(DateTime.Now)
GetAPIObjectExp(myObject)
The return type respectively, IntExp, StringExp, DoubleExp, DateExp and ObjectExp. All return types inherit from a class (which interestingly is a generic type) StaticOperator<T>
where T is the datatype.
Is it possible to write a generic method in my codebase which redirects calls to the suitable API method based on the datatype which is passed in?
In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.
You can create an instance of generic classes by specifying an actual type in angle brackets. The following creates an instance of the generic class DataStore . DataStore<string> store = new DataStore<string>(); Above, we specified the string type in the angle brackets while creating an instance.
(Yes, this is legal code; see Java Generics: Generic type defined as return type only.) The return type will be inferred from the caller.
From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.
Seems to me you don't need a generic method at all, just a wrapper method for each supported argument type:
public IntExp GetExpression(int value)
{
return GetIntExp(value);
}
public StringExp GetExpression(string value)
{
return GetStringExp(value);
}
and so on (assuming your goal is to use the same name for all the ways of getting an expression).
Something like
private Dictionary<Type, Func<object, object>> _funcMapping = new Dictionary<Type, Func<object, object>> {
{typeof(Int), (input) => GetIntExp((int)input)},
{typeof(string), (input) => GetStringExp((string)input)},
...
};
public StaticOperator<TType> GetExp<TType>(TType target) {
Func<object, object> func;
if (!_funcMapping.TryGetValue(typeof(TType), out func))
throw new NotImplementedException();
return (StaticOperator<TType>)func(target);
}
is totally possible, but certainly have scaling problems and quite unsafe as requires a lot of casting.
Of course you can rewrite it using if .. elseif .. elseif .. elseif .. else
, but all in all it's just a checking if we have a suitable method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With