Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# list reflection
I am struggling with calling a method with reflection...
 
The method signature is as follows: (changed the actual names...)
 
I have a interface called :
 
public interface ICharacteristics
   {
       Score calculateScore(int ScorecardID, string UniqueID, ArrayList CharacteristicsValues);
   }
 
Then i have another class called:
 
public class ScoreSmartCharValues
   {
       private string name;
       private int value;
 
       public int Value
       {
           get { return this.value; }
           set { this.value = value; }
       }
 
       public string Name
       {
           get { return name; }
           set { name = value; }
       }
 
       public ScoreSmartCharValues(int value, string name)
       {
           this.name = name;
           this.value = value;
       }
 
       public ScoreSmartCharValues()
       {
 
       }
   }
 
another class as follow:
 
public Score calculateScore(int ScorecardID, string UniquesID, ArrayList CharacteristicsValues)
        {
 
//Do something and return Score;
 
 return new Score();
}
 

 
Ok so once build... generates a DLL score.dll
 

The code that i use is simple to call reflection and invoke the method:
 
Assembly assembly = Assembly.LoadFrom(@"Score.dll");
 

foreach (Type type in assembly.GetTypes())
            {
                // Pick up a class
                if (type.IsClass == true)
                {
                    Console.WriteLine("...Found Class : {0}", type.FullName);
 
                    // If it does not implement the IBase Interface, skip it
                    if (type.GetInterface("ICharacteristics") == null)
                    {
                        continue;
                    }
 
                    // If however, it does implement the IBase Interface,
                    // create an instance of the object
                    object ibaseObject = Activator.CreateInstance(type);
                    List<ScoreSmartCharValues> CharacteristicsValues = new List<ScoreSmartCharValues>();
                    CharacteristicsValues.Add(new ScoreSmartCharValues(1, "robs"));
 
                    object oObjectType = new object();
                    oObjectType = CharacteristicsValues;
                    // Create the parameter list
                    object[] arguments = new object[] { 10, "test", CharacteristicsValues };
                    object result;
                    // Dynamically Invoke the Object
                    Console.WriteLine("......Dynamically Invoking compute() on {0} Class", type.FullName);
               
                    result = type.InvokeMember("calculateScore",
                                                BindingFlags.Default |BindingFlags.InvokeMethod,
                                                null,
                                                ibaseObject,
                                                arguments);
 
                    Console.WriteLine("......Result is: {0}", result);
                }
            }
 

I get a method not found...
 
If i change the argument to send in Null in the place of the list it works...
Posted 2-Jun-11 22:33pm
Edited 3-Jun-11 3:54am
v3
Comments
BobJanova at 3-Jun-11 8:55am
   
The reason the bind is failing is that the list type you generate (List<scoresmartcharvalues>) and the one the method accepts (List<Characteristics>) are not compatible. But please see Fredrik's answer and my comment thereunder: you don't need to use runtime binding at all.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

I'm not sure, but it looks to me like you don't need the reflection bit at all.
Can't you just cast you ibaseObject to a ICharacteristics and invoke the calculateScore method normally?
 
If you do need to call it using reflection, here's a working example of what I think you're trying to do:
 
using System;
using System.Collections;
 
namespace ReflectionTest
{
 
    public interface ICharacteristics
    {
 
        int calculate(int number, string Name, IList Characterstics);
    }
 
    public class MyImplementation : ICharacteristics
    {
        public int calculate(int number, string Name, IList Characterstics)
        {
            return 42;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            object[] instances = new object[] { "Test", new MyImplementation() };
 
            foreach (object instance in instances)
            {
                if (instance is ICharacteristics)
                {
                    Type type = instance.GetType();
                    object result = type.InvokeMember("calculate", System.Reflection.BindingFlags.InvokeMethod, null, instance,
                        new object[] { 1, "Name", new ArrayList()});
                }
            }
        }
    }
}
 
Hope this helps,
Fredrik Bornander
  Permalink  
Comments
BobbyBlueEyes at 3-Jun-11 5:41am
   
I have to use reflection as the calculate part is in a seperate DLL
BobJanova at 3-Jun-11 8:45am
   
No you don't. The interface should be defined in the main assembly, or a shared DLL which both the main assembly and the plugins can interface, so you can reference it, even if the implementing class is not defined in this assembly. This is fundamental to a good plugin architecture.
 
You do -not- need the implementing class to be visible at compile time. Only the interface.
 
Then you can do:
 
Assembly assembly = Assembly.LoadFrom(@"name.dll");
foreach (Type type in assembly.GetTypes())
{
// Pick up a class
if (type.IsClass == true)
{
Console.WriteLine("...Found Class : {0}", type.FullName);

// If it does not implement the IBase Interface, skip it
if (type.GetInterface("ICharacteristics") == null)
{
continue;
}

// If however, it does implement the IBase Interface,
// create an instance of the object
ICharacteristics ibaseObject = (ICharacteristics)Activator.CreateInstance(type);
List<Characteristics> CharacteristicsValues = new List<Characteristics>();
CharacteristicsValues.Add(new ScoreSmartCharValues(1, "robs"));

int result = ibaseObject.calculateScore(10, "Test", CharacteristicsValues);
}
}
BobJanova at 3-Jun-11 8:53am
   
5 for better higher level advice.
BobbyBlueEyes at 3-Jun-11 9:07am
   
Ok i have updated the solution....
 
I cannot cast to ICharacteristics - what am i missing here?
BobbyBlueEyes at 3-Jun-11 9:33am
   
ok got i working BobJanova you where absolutely right - should have followed the basic architecture best parctices.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Hi,
 
I would suggest to use dynamic where you find GetType() kind of code. Will give better performance too.
 
Soultion:
 
In this line
// If however, it does implement the IBase Interface,
// create an instance of the object
object ibaseObject = Activator.CreateInstance(type);
 
instead of taking it as an object type above. Please use dynamic type as below and calling will simpler and better for sure.
 
dynamic ibaseObject = Activator.CreateInstance(type);</pre>
 
Now,
 
Call whatever you want will be so easy and better in performance.
 
EX: ibaseObject.calculate(5, "name", arguments);
 
In above code, Like any other class object you can call those methods of class without any invoke method of reflection here.
 
Sure this will help you in reflection.
 
Hope this will help you
 
For more Information Please refer below link :
 
Perform Reflection and XML Traversing Using the dynamic Keyword in C#[^]
 

Thank You Smile | :)
  Permalink  
v2
Comments
BobbyBlueEyes at 3-Jun-11 5:49am
   
Hi Thanks for the help,
 
But if i send in a List i still get the error, if i send in a null value then the method does get executed....
BobJanova at 3-Jun-11 8:52am
   
dynamic still uses similar runtime binding methods under the covers to Reflection, so it doesn't really solve the problem, although it does make reflection-based code cleaner in the source.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Something like this?
 
 
    class Program {
        static void Main(string[] args) {
 
            List<ScoreSmartCharValues> characterstics = new List<ScoreSmartCharValues>();
            characterstics.Add(new ScoreSmartCharValues(1, "Hello"));
            characterstics.Add(new ScoreSmartCharValues(2, "World"));
 
            DoSomethingUsefull doSomethingUsefull = new DoSomethingUsefull();
 
            var methodToCall = doSomethingUsefull.GetType().GetMethod(
                "calculate",
                new Type[] {
                typeof(int),
                typeof(String),
                typeof(List<ScoreSmartCharValues>)
            }
            );
            methodToCall.Invoke(doSomethingUsefull, new Object[] { 1, "Foobar", characterstics });
            Console.WriteLine("Done");
            Console.ReadLine();
        }
 
    }
 
    public class DoSomethingUsefull {
 
        public int calculate(int number, string Name, List<ScoreSmartCharValues> Characterstics) {
 
            Console.WriteLine(number);
            Console.WriteLine(Name);
            foreach (var characterstic in Characterstics) {
                Console.WriteLine("{0} -> {1}", characterstic.Name, characterstic.Value);
            }
 
            return 0;
 
        }
 

    }
 
    public class ScoreSmartCharValues { 
        private string name; 
        private int value; 
        
        public int Value { 
            get { return this.value; } 
            set { this.value = value; } 
        } 
        
        public string Name { 
            get { return name; } 
            set { name = value; } 
        } 
        
        public ScoreSmartCharValues(int value, string name) { 
            this.name = name; this.value = value; 
        } 
        
        public ScoreSmartCharValues() { } 
    }
  Permalink  
v2
Comments
BobbyBlueEyes at 3-Jun-11 6:34am
   
The List being sent is of type class - that contains a int and a string as properties.
s_mon at 3-Jun-11 6:58am
   
Sorry, I'm not quite sure what you mean. Did you mean the IList?
BobbyBlueEyes at 3-Jun-11 7:55am
   
please see my code below:
 
public class ScoreSmartCharValues
{
private string name;
private int value;
 
public int Value
{
get { return this.value; }
set { this.value = value; }
}
 
public string Name
{
get { return name; }
set { name = value; }
}
 
public ScoreSmartCharValues(int value, string name)
{
this.name = name;
this.value = value;
}
 
public ScoreSmartCharValues()
{

}
}
 

I create a List of this type.
 
so this is my method signature:
 
Score calculateScore(int ScorecardID, string UniqueID, List CharacteristicsValues);
 

When i try to use reflection i cannot call the method...
 
I have change the signature to rather use a type of type object then it works fine...
s_mon at 3-Jun-11 8:07am
   
Changed my solution...
s_mon at 3-Jun-11 8:29am
   
Oops... now I see your Problem:
 
You do...

object oObjectType = new object();
oObjectType = CharacteristicsValues;
 
object[] arguments = new object[] { 10, "test", CharacteristicsValues };

 
but the signature of your method is...
public int void calculate(int number, string Name, List Characterstics)
 
Your invoke does not match the signature of the method you want to call...
BobbyBlueEyes at 3-Jun-11 8:50am
   
ok let me change me code completely to show you what i'm doing ...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Advertise | Privacy | Mobile
Web04 | 2.8.1411022.1 | Last Updated 3 Jun 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100