How to create reference of an interface class through Reflection in C# - c#

I'm using repository structure in my application.
I have a interface class IDemoService
public interface IDemoService
{
bool CreateDemo(Demo demo);
bool UpdateDemo(Demo demo);
bool DeleteDemo(int id);
Demo GetDemo(int id);
Demo GetDemoServiceByName(string name);
IEnumerable<Demo> GetAllDemo();
void SaveRecord();
}
with using System.Reflection; I need to create reference like
IDemoService iDemoService;
I've tried this way so far:
var iDemoServiceClass = asm.GetTypes().Where(p =>
p.Namespace == nameSpace &&
p.Name == "IDemoService"
).ToList();
Type iDemoServiceClassType = iDemoServiceClass.FirstOrDefault();
var className = iDemoServiceClassType.Name;
var functionName = "Get" + iDemoServiceClassType + "ByName";
MethodInfo getMethod = demoServiceClassType.GetMethod(functionName);
var instanceCreate = Activator.CreateInstance(iDemoServiceClassType);//, null); //here I want to create reference instead instance
ParameterInfo[] parameters = getMethod.GetParameters();
if (parameters.Length > 0)
{
object[] parametersArray = new object[] { "RequiredDemo" };
var demoObj = getMethod.Invoke(instanceCreate, parametersArray);
}
Since it is interface so can't create instance but reference is possible. So, is it possible anyway to create reference using Reflection or any other way?
Please help me right way. Thanks advance :D

You can't instantiate an interface, and so you can't create a reference to it. You need a concrete type implementing that interface, than you can use Activator.CreateInstance.
The point is that an interface is just a contract, not a real implementation; so for example you have no method bodies. Imagine the compiler letting you activate the interface, what is supposed to happen when you call a method without a body?
At least you need an empty class in the form DemoService:IDemoService, than you get a reference to it.
Hope it helps.

Related

How to call specific function depending on a variable?

I'm generating a random number from 1-1000. I have 200 functions named function1, function4, function 10, function 11, etc. What I would like to do is execute a specific function depending on if the number generated requires a function, and ignore it if not.
My first thought was to create an int[] containing all of the values that would trigger a function, and if the int[] contains the random number to use if statements to figure out what the number is. I'm concerned that it must be a really crude solution to an easy problem though.
I know the "best way" to do something is subjective, but is there a better way to accomplish this?
UPDATE: As per comments, I should probably have started out by pointing out that doing this for 200 functions is probably a good sign that there is some serious issue in your design. This is probably an XY question where you are trying to solve a problem in some crazy way and asking about your intended solution instead of asking about the problem itself.
That said I'll leave the original answer because it's still good advice when mapping a reasonable amount of function calls that can/will change during the life cylce of your app or dynamically as the code runs.
I won't get into why you are doing this, but I'll try to at least point you in the right direction so this doesn't become a complete nightmare when you need to modify/expand behavior:
You can map numbers to function calls using delegates and a dictionary. Assuming your functions take no arguments and return void you'd do:
var functionsMap = new Dictionary<int, Action>();
//map functions
var r = getSomeRandomNumber();
if (functions.TryGetValue(r), out var a)
a(); //invoke function
Mapping functions is simply adding keys and values:
functionsMap.Add(1, () => function1());
functionsMap.Add(3, () => function3());
//etc.
If your functions take arguments or return values, you'd use the adequate delegate: Action<T>, Func<T1, T2> etc.
You can use reflection to invoke appropriate method:
Type exampleType = exampleObject.GetType();
MethodInfo exampleMethod = exampleType.GetMethod(methodName);
exampleMethod.Invoke(this, null);
Where methodName can be created using your random number.
Without commenting on the wisdom of having 200 functions named the way yours are, you can use reflection to determine whether a given functionX() exists, like so:
public void ExecuteDynamicMethod(int number)
{
// Modify these two lines with your app's dll/exe and class type:
Assembly assembly = Assembly.LoadFile("...Assembly1.dll");
Type type = assembly.GetType("YourClassType");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod("function" + number);
if (methodInfo != null)
{
object classInstance = Activator.CreateInstance(type, null);
methodInfo.Invoke(classInstance, null); // null = "no function arguments"
}
}
}
This can then be called for a given value like
ExecuteDynamicMethod(14);
See this SO answer for the inspiration behind this.
Reflection can be used for this purpose. I want to give and keep below example for not only the objective of the question but also for future reference. Also, of course that many function is not good but below code shows the approach that can work with many functions if they have similar name (like starting with "function" keyword).
Assume below is Methods.cs
using System;
using System.Reflection;
namespace YourMethodNamespace
{
public class YourMethodClass
{
public void function1()
{
Console.WriteLine("Function-1");
}
public void function2()
{
Console.WriteLine("Function-2");
}
...
public void function200()
{
Console.WriteLine("Function-200");
}
public static void invokeMethodsDynamically(int randomNumber){
Type yourClassType = typeof(YourMethodClass);
ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(Type.EmptyTypes);
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{});
//If the constructor has parameters, then we can pass them by this way. Like below;
/*ConstructorInfo yourClassConstructorInfo = yourClassType.GetConstructor(new[]{typeof(int)});
object yourClassObject = yourClassConstructorInfo.Invoke(new object[]{3});
*/
MethodInfo[] methodInfoArr = yourClassType.GetMethods();
foreach(MethodInfo methodInfo in methodInfoArr){
if(methodInfo.Name == "function" + randomNumber){
methodInfo.Invoke(yourClassObject, null);
}
}
}
}
}
Let's say below is Program.cs
using System;
using YourMethodNamespace;
namespace YourProgramNamespace
{
public class YourProgramClass
{
public static void Main()
{
Random random = new Random();
int randomNumber = random.Next(1, 201);
//If Methods.cs is in another Assembly
/*string pathToDllAssembly = #"Domain.dll";
Assembly dllAssembly = Assembly.LoadFrom(pathToDllAssembly);
Type methodsClassType = dllAssembly.GetType("YourMethodNamespace.YourMethodClass");
ConstructorInfo methodClassConstructorInfo = methodsClassType.GetConstructor(Type.EmptyTypes);
object methodsClassObject = methodClassConstructorInfo.Invoke(new object[]{});
MethodInfo methodInfo = methodsClassType.GetMethod("invokeMethodsDynamically");
methodInfo.Invoke(methodsClassObject, new object[]{randomNumber});
*/
YourMethodClass.invokeMethodsDynamically(randomNumber, null);
}
}
}
Also for testing and observing, below link can be used.
https://repl.it/#erdsavasci/ReflectionTest

Attach Generic method event handler with unknow type

I need to attach this handler to a RadListView Column creation, by adding a DataSource to the control.
public void GenericColumnCreatingHandler<T>(object sender, ListViewColumnCreatingEventArgs e)
{
e.Column.Visible = BaseEntity<int>.MemberVisibility<T>
(e.Column.FieldName, TelerikPropertyVisibilityAttribute.VisibilityTypeEnum.BaseDetails);
e.Column.HeaderText = CaricaTestoLocale(e.Column.HeaderText, "Col_" + e.Column.HeaderText);
e.Column.BestFit();
e.Column.AutoSizeMode = ListViewBestFitColumnMode.AllCells;
}
My problem is that I need to perform the handler attach from this other generic method:
private void PopulateRecord(TipoTabellaBase tipo)
{
Type generic = typeof(CommonTableService<>);
Type[] typeArgs = { tipo.Tipo };
var constructed = generic.MakeGenericType(typeArgs);
var instance = Activator.CreateInstance(constructed);
if (instance == null)
return;
MethodInfo getEntities = constructed.GetMethod("GetEntitiesWithNoParameters");
//getEntities = getEntities.MakeGenericMethod(typeArgs);
var result = (IEnumerable<BaseEntity<int>>)getEntities.Invoke(instance, null);
lvRecords.ColumnCreating += base.GenericColumnCreatingHandler<BaseEntity<int>>;
lvRecords.DataSource = result;
BestFit(lvRecords);
generic = null;
typeArgs = null;
constructed = null;
getEntities = null;
instance = null;
}
The problematic row is this one:
lvRecords.ColumnCreating += base.GenericColumnCreatingHandler<BaseEntity<int>>
because BaseEntity is EF base type for all Entities, but this is not enought for the BaseEntity.MemberVisibility method; this method need to know the exact entity type to set the visible properties (and, of course, grid column) based on specific custom attribute on that.
Question is: how I can call base.GenericColumnCreatingHandler where T is TipoTabellaBase tipo.Tipo (type) without knowing type at design time?
Any help would be very appreciated!
Thanks is advance.
Daniel
Please note that this solution is untested.
You will have to instantiate the strongly-typed version of base.GenericColumnCreatingHandler<T> at runtime.
From your code, I figure you already know how to obtain a MethodInfo instance for a given method. You will need to get the MethodInfo for base.GenericColumnCreatingHandler<T> (let's call it genericMethodInfo).
Then, you can create a strongly-typed version of that method with MakeGenericMethod:
MethodInfo typedMethodInfo = genericMethodInfo.MakeGenericMethod(new[] {
typeof(BaseEntity<int>)
});
Once that is done, you need to invoke CreateDelegate to obtain something that you can assign to the ColumnCreating event, as described here or here:
lvRecords.ColumnCreating +=
(ListViewColumnCreatingEventHandler)typedMethodInfo.CreateDelegate(
typeof(ListViewColumnCreatingEventHandler), this);
EDIT: Replaced base with this in the last code sample. In case an inherited method is specifically required, this has to be taken care of while retrieving genericMethodInfo.

Can you pass generic delegate without the type parameter?

I have three projects
MVC Web application
Service application which is kind of two layers business/repository
Entity framework (all EF configuration lives here)
MVC references > service
Service references > EF
I have these three methods currently that do some work.
public bool StoreUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
public bool RemoveUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
public bool CommitUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
I call these three methods from my controller using these interfaces which delegate to the work methods above:
Boolean StoreUpload(UploadInformation information);
Boolean RemoveUpload(UploadInformation information);
Boolean CommitStoredDocuments(UploadInformation information);
Based on a condition from UploadTypes enumeration in a switch I call the correct work method. I do this because I don't want my mvc project to have access to the EF database types otherwise I know someone is going to start querying data from all over the application. I use these switch statements for all interfaced methods:
public bool StoreUpload(UploadInformation information)
{
switch (information.Type)
{
case UploadTypes.AutoIncident:
return RemoveUpload<AutoIncident>(information);
case UploadTypes.Incident:
return RemoveUpload<IncidentInjury>(information);
case UploadTypes.Inspection:
return RemoveUpload<Inspection>(information);
case UploadTypes.OtherIncident:
return RemoveUpload<OtherIncident>(information);
default:
return false;
}
}
public bool RemoveUpload(UploadInformation information) { ... }
public bool CommitStoredUpload(UploadInformation information) { ... }
This method might shed a little light on what the types parameters are being used for. I am updating tables in a generic way using EF.
private bool CommitStoredDocuments<T>(UploadInformation information) where T : class, IUploadEntity
{
var uploads = GetStoredUploads(information.UniqueId);
var entity = db.Set<T>().Include(e => e.Uploads)
.Single(e => e.UniqueId == information.UniqueId);
entity.Uploads.AddRange(uploads);
...
}
It would be nice to be able to pass the work method which requires a type parameter as a delegate to the switch work method calls.
public bool DoSomeWork(delegateMethod, information) {
switch(information.Type) {
case UploadTypes.AutoInciden:
return delegateMethod<AutoIncident>(information);
...
}
}
Can this be done?
Also, I had trouble constructing a good title for this question so please comment if these is a better way to describe the challenge.
It cannot be done directly due to several reasons.
First of all, as you probably noticed, delegateMethod<FooBar>(information) simply does not compile. This is because in your example the delegateMethod is a local variable (method parameter actually, but still a variable), and you cannot apply "type arguments" <FooBar> to a variable - you can apply them only on an identifier that indicates a (generic) type or a (generic) method.
Second reason is more interesting. When you pass a method as a delegate, the delegate actually catches the whole method signature, including all parameter types.
void Blah<T>(UploadInformation information){ ... }
var one = new Action<int>(Blah); // -> Blah<int>
var two = new Action<float>(Blah); // -> Blah<float>
var thr = new Action<andsoon>(Blah); // -> Blah<andsoon>
MagicDoSomeWork(one, ...); // these all
MagicDoSomeWork(two, ...); // delegates are already bound
MagicDoSomeWork(thr, ...); // and remember their concrete T
You need to actually specify the type for the Action so a proper version of generic method will be picked from a general description called Blah. These delegates are bound to concrete versions of the method and will accept only that types. These delegates are 'closed' in terms of their type arguments. Using normal ways, the MagicDoSomeWork will simply have no way of altering the T which these delegates already have remembered.
That two things are a kind of show stoppers, since by normal code only, you cannot write things like
var nope1 = new Action(Blah); // ctor for Action NEEDS type parameter
since Action constructor simply requires a type parameter. And once you pass any, it will lock the Blah type arguments
Also you cannot use open delegates:
var nope1 = new Action<>(Blah); // can't use empty <> in this context :(
since new operator requires a full type to create an object.
However, with a bit of reflection voodoo, it is possible to analyze and build a generic type or a generic method dynamically.
// first, build the delegate in a normal way
// and pick anything as the type parameters
// we will later replace them
var delegateWithNoType = new Action<object>(Blah);
// delegate has captured the methodinfo,
// but uses a stub type parameter - it's useless to call it
// but it REMEMBERS the method!
// .... pass the delegate around
// later, elsewhere, determine the type you want to use
Type myRealArgument;
switch(..oversomething..)
{
default: throw new NotImplemented("Ooops");
case ...: myRealArgument = typeof(UploadTypes.AutoIncident); break;
...
}
// look at the delegate definition
var minfo = delegateWithNoType.Method;
var target = delegateWithNoType.Target; // probably NULL since you cross layers
var gdef = minfo.GetGenericDefinition();
var newinfo = gdef.MakeGenericMethod( myRealArgument );
// now you have a new MethodInfo object that is bound to Blah method
// using the 'real argument' type as first generic parameter
// By using the new methodinfo and original target, you could now build
// an updated delegate object and use it instead the original "untyped" one
// That would be a NEW delegate object. You can't modify the original one.
// ...but since you want to call the method, why don't use the methodinfo
UploadInformation upinfo = ... ;
newinfo.Invoke(target, new object[] { upinfo });
// -> will call Blah<UploadTypes.AutoInciden>(upinfo)
word of warning: this is a sketch to show you how the delegate.Method/Target and methodinfo and getgenericdefinition and makegenericmethod work. I wrote it from memory, never compiled, never ran. It can contain minor typos, overlooked things and invisible rainbow unicorns. I didn't noticed any. Probably because they were invisible.
You can do it like this
public bool Invoke(EntityType entityType, ActionType action, Object[] arguments)
{
var actionType = Enum.GetName(typeof(ActionType), action);
var type = GetType();
var method = type.GetMethods().Single(m => m.IsGenericMethod && m.Name == actionType);
switch (entityType)
{
case EntityType.IncidentInjury:
var genericMethod = method.MakeGenericMethod(typeof(IncidentInjury));
return (bool)genericMethod.Invoke(this, arguments);
default:
return false;
}
}
The enum will just be a list of methods that I want to invoke this way and I create a base class for my services so I don't have to pass the instance to the Invoke method.
Instead of using delegates, consider using an interface (or abstract class). This way, your methods can retain their generic nature.
For example, if you create an interface like:
interface IUploadAction
{
bool Perform<T>(UploadInformation information)
where T : class, IUploadEntity;
}
Note that the T is not exposed in the type, it's only on the method. This is the key part.
Now you can implement this for your database methods:
class CommitStoredDocuments : IUploadAction
{
public bool Perform<T>(UploadInformation information)
where T : class, IUploadEntity
{
var uploads = GetStoredUploads(information.UniqueId);
var entity = db.Set<T>().Include(e => e.Uploads)
.Single(e => e.UniqueId == information.UniqueId);
entity.Uploads.AddRange(uploads);
//...
}
}
Your switching/dispatching method can look like this:
public bool DoAction(IUploadAction action, UploadInformation information)
{
switch (information.Type)
{
case UploadTypes.AutoIncident:
return action.Perform<AutoIncident>(information);
case UploadTypes.Incident:
return action.Perform<IncidentInjury>(information);
case UploadTypes.Inspection:
return action.Perform<Inspection>(information);
case UploadTypes.OtherIncident:
return action.Perform<OtherIncident>(information);
default:
return false;
}
}
And then you can write something like:
IUploadAction storeUpload;
public bool StoreUpload(UploadInformation information) => DoAction(storeUpload, information);

Object of type 'customObject' cannot be converted to type 'customObject'

I receive the following error when I invoke a custom object
"Object of type 'customObject' cannot be converted to type 'customObject'."
Following is the scenario when I am get this error:
I invoke a method in a dll dynamically.
Load an assembly
CreateInstance....
When calling MethodInfo.Invoke() passing int, string as a parameter for my method works fine => No exceptions are thrown.
But if I try and pass one of my own custom class objects as a parameter, then I get an ArgumentException exception, and it is not either an ArgumentOutOfRangeException or ArgumentNullException.
"Object of type 'customObject' cannot be converted to type 'customObject'."
I am doing this in a web application.
The class file containing the method is in a different project. Also the custom object is a separate class in the same file.
There is no such thing called a static assembly in my code. I am trying to invoke a webmethod dynamically. this webmethod is having the customObject type as an input parameter. So when i invoke the webmethod i am dynamically creating the proxy assembly and all. From the same assembly i am trying to create an instance of the cusotm object assinging the values to its properties and then passing this object as a parameter and invoking the method. everything is dynamic and nothing is created static.. :(
add reference is not used.
Following is a sample code i tried to create it
public static object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)
{
System.Net.WebClient client = new System.Net.WebClient();
//-Connect To the web service
using (System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl"))
{
//--Now read the WSDL file describing a service.
ServiceDescription description = ServiceDescription.Read(stream);
///// LOAD THE DOM /////////
//--Initialize a service description importer.
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
importer.AddServiceDescription(description, null, null);
//--Generate a proxy client. importer.Style = ServiceDescriptionImportStyle.Client;
//--Generate properties to represent primitive values.
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
//--Initialize a Code-DOM tree into which we will import the service.
CodeNamespace nmspace = new CodeNamespace();
CodeCompileUnit unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
//--Import the service into the Code-DOM tree. This creates proxy code
//--that uses the service.
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
if (warning == 0) //--If zero then we are good to go
{
//--Generate the proxy code
CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
//--Compile the assembly proxy with the appropriate references
string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
CompilerParameters parms = new CompilerParameters(assemblyReferences);
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
//-Check For Errors
if (results.Errors.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError oops in results.Errors)
{
sb.AppendLine("========Compiler error============");
sb.AppendLine(oops.ErrorText);
}
throw new System.ApplicationException("Compile Error Occured calling webservice. " + sb.ToString());
}
//--Finally, Invoke the web service method
Type foundType = null;
Type[] types = results.CompiledAssembly.GetTypes();
foreach (Type type in types)
{
if (type.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol))
{
Console.WriteLine(type.ToString());
foundType = type;
}
}
object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString());
MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
return mi.Invoke(wsvcClass, args);
}
else
{
return null;
}
}
}
I can't find anything static in what I do.
Any help is greatly appreciated.
Regards,
Phani Kumar PV
Have you looked at what the proxy class looks like that gets generated? You don't need the proxy to call a web service. Just create a class that inherits from SoapHttpClientProtocol and call Invoke(methodName, params).
You are making this SO much more complicated than you need to. Honestly.
EDIT
If you create a class like this:
public class SoapClient : SoapHttpClientProtocol
{
public SoapClient()
{
}
public object[] Invoke(string method, object[] args)
{
return base.Invoke(method, args);
}
}
and call it like this:
SoapClient soapClient = new SoapClient();
soapClient.Url = webServiceAsmxUrl;
soapClient.Invoke(methodName, args);
I think you will see that it has the exact same results as what you are doing.
Let me try to explain the most probable reason for the problem to come in my approach.
When I invoked a method in the assembly called as "methodname" in the webservice I am trying to pass the parameters required for that as args[] to the function "CallWebService"
This args[] when passed will be successfully working when I try to pass a normal parameters like primitive types including string.
But this is what I did when I tried to pass a custom object as a parameter.
Three things that are done in this.
create an object of that type outside the CallWebService function (using reflection). when I did that way what happens is an instance of the customobject created with a temporary dll name internally.
once I set the set the properties of the object and send it across to the CallWebService function as an object in the args array.
I tired to create an instance of the webservice by creating the dynamic dll.
object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString());
When I finally tried to invoke the method with the instance of the dynamic assembly created
I tried to pass the customobject that is created at step 1,2 via args property.
at the time of invocation the CLR tries to see if the customobject that is passed as input and the method that is being invoked are from the same DLL.
which is obviously not from the way the implementation is done.
So following is the approach that should be used to overcome the problem
I need to create the custom object assembly with the same assembly that I used to the create the webservice instance..
I implemented this approach completely and it worked out fine
MethodInfo m = type.GetMethod(methodName);
ParameterInfo[] pm = m.GetParameters();
object ob;
object[] y = new object[1];
foreach (ParameterInfo paraminfo in pm)
{
ob = this.webServiceAssembly.CreateInstance(paraminfo.ParameterType.Name);
//Some Junk Logic to get the set the values to the properties of the custom Object
foreach (PropertyInfo propera in ob.GetType().GetProperties())
{
if (propera.Name == "AppGroupid")
{
propera.SetValue(ob, "SQL2005Tools", null);
}
if (propera.Name == "Appid")
{
propera.SetValue(ob, "%", null);
}
}
y[0] = ob;
}
this can occur when the version of a dll you have referenced in your reflected code is different from the version of that dll in your compiled code.
This is an old thread, but I just had a similar problem. I looked on here, this one popped up, but I saw no useful solutions.
The OP's error was this: Object of type 'customObject' cannot be converted to type 'customObject'.
My very similar error was this: Object of type 'System.String' cannot be converted to type 'System.Windows.Forms.AccessibleRole'.
Here is how I solved my problem:
I performed a Find and Replace (use CRTL+SHIFT+F to bring the dialog box up) search in the Current Project for the term AccessibleRole.
Within one of the Form's Designer's was a place where I was assigning an AccessibleRole value to a String variable using ToString().
I fixed this, and my problem went away.
I hope this provides help to others.

How to call the correct overloaded function at runtime?

How do I call the correct overloaded function given a reference to an object based on the actual type of the object. For example...
class Test
{
object o1 = new object();
object o2 = new string("ABCD");
MyToString(o1);
MyToString(o2);//I want this to call the second overloaded function
void MyToString(object o)
{
Console.WriteLine("MyToString(object) called.");
}
void MyToString(string str)
{
Console.WriteLine("MyToString(string) called.");
}
}
what I mean is there a better option than the following?
if(typeof(o) == typeof(string))
{
MyToString((string)o);
}
else
{
MyToString(o);
}
May be this can be done using reflection?
Ok as soon as I hit post I remembered this can indeed be done using reflection...
var methInfo = typeof(Test).GetMethod("MyToString", new Type[] {o.GetType()});
methInfo.Invoke(this, new object[] {o});
You could just use ternary operators to code this using a single clean line of code:
MyToString(o is string ? (string)o : o);
Why not have a toString() function in the actual object itself? That way you can call myObj.toString() and the relative output is given. Then you don't have to do any comparisons.

Categories