?
Solved

Reflection and Instance Objects

Posted on 2005-04-11
8
Medium Priority
?
221 Views
Last Modified: 2010-04-16
I am building a class factory that needs to dynamically add classes to a hash table based on the DLLs found in a given directory.  I am using Assembly.FromFile to pull the assembly into my method, however I do not know how to create an instance based off of that assembly in order to place the instance in my hash table.
I have tried a wide variety of things - from other sources and from this site - and nothing appears to work.  I have a simple class, for testing, that has a simple method - WriteAnotherLine - yet when I interrogate the class, I do not see my method:

Type[] theseTypes = thisAssembly.GetTypes();
foreach(Type thisType in theseTypes)
{
     Console.WriteLine("Type: " + thisType.FullName);
     MemberInfo[] mi = thisType.GetMembers();
     foreach(MemberInfo thisMem in mi)
          Console.WriteLine("Member Name: " + mi[0].Name);
     EventInfo[] theseEs = thisType.GetEvents();
     foreach(EventInfo thisE in theseEs)
          Console.WriteLine("Event: " + thisE.Name);
     FieldInfo[] theseFs = thisType.GetFields();
     foreach(FieldInfo thisF in theseFs)
          Console.WriteLine("Field: " + thisF.Name);
     MethodInfo[] theseMs = thisType.GetMethods();
     foreach(MethodInfo thisM in theseMs)
          Console.WriteLine("Method: " + thisM.Name);
     Type[] theseNs = thisType.GetNestedTypes();
     foreach(Type thisN in theseNs)
          Console.WriteLine("Nested Type: " + thisN.FullName);
     PropertyInfo[] thesePs = thisType.GetProperties();
     foreach(PropertyInfo thisP in thesePs)
          Console.WriteLine("Property: " + thisP.Name);
     Console.WriteLine("----------------------------------------------------------------------");
}

Can you please help?!?
0
Comment
Question by:ktola
  • 5
  • 3
8 Comments
 
LVL 17

Expert Comment

by:Jesse Houwing
ID: 13756004
Type[] theseTypes = thisAssembly.GetTypes();
Hashtable objects = new HashTable(theseTypes.Count);
foreach(Type thisType in theseTypes)
{
         ConstructorInfo ci = thisType.GetConstructor(new type[]{})
         object o = ci.Invoke(new object[]{})
         objects.Add(thisType.FullName, o);
}
0
 

Author Comment

by:ktola
ID: 13756141
So how do I then call the WriteAnotherLine method?
0
 
LVL 17

Expert Comment

by:Jesse Houwing
ID: 13756275
You could call it through reflection:

                  Type[] theseTypes = thisAssembly.GetTypes();
                  Hashtable objects = new HashTable(theseTypes.Count);
                  foreach(Type thisType in theseTypes)
                  {
                        ConstructorInfo ci = thisType.GetConstructor(new type[]{});
                        object o = ci.Invoke(new object[]{});
                        objects.Add(thisType.FullName, o);
                        MethodInfo mi = thisType.GetMethod("WriteAnotherLine", new type[]{});
                        mi.Invoke(o, new object[]{});
                  }

A better solution would be to have your dynamically loaded types inherit from some interface that has the required methods and do it like this:

                  Type[] theseTypes = thisAssembly.GetTypes();
                  Hashtable objects = new HashTable(theseTypes.Count);
                  foreach(Type thisType in theseTypes)
                  {
                        ConstructorInfo ci = thisType.GetConstructor(new type[]{});
                        object o = ci.Invoke(new object[]{});
                        if (o!=null)
                        {
                              objects.Add(thisType.FullName, o);
                              MyInterface myInterfaceObject = (MyInterface)o;
                              o.WriteAnotherLine();
                        }
                  }

with MyInterface as follows:

public interface MyInterface
{
      void WriteAnotherLine();
}
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 17

Expert Comment

by:Jesse Houwing
ID: 13757354
That ofcourse should have been:

MyInterface myInterfaceObject = (MyInterface)o;
myInterfaceObject .WriteAnotherLine();
0
 

Author Comment

by:ktola
ID: 13761088
This is frsturating - I know your solution will work, I just cannot seem to get it to want to cooperate.  I have the following:

public interface MyInterface
{
     void WriteAnotherLine();
}

public class Class1 : MyInterface
{
     public Class1() {}
     public void WriteAnotherLine()
     {
          Console.WriteLine("Writing Another Line...");
     }
}

In a seperate project (e.g. different assembly) with a reference to the first assembly (for the Interface), I have the following pertinent code:

thisAssembly = Assembly.LoadFile("FILE_LOCATION");
Console.WriteLine(thisAssembly.FullName);          //This pulls up the correct DLL
Type[] theseTypes = thisAssembly.GetTypes();
Hashtable objects = new Hashtable(theseTypes.Length);
foreach(Type thisType in theseTypes)
{
     ConstructorInfo ci = thisType.GetConstructor(new Type[] {});
     object o = ci.Invoke(new object[] {});
     if(o != null)
     {
          Console.WriteLine(thisType.Fullname);          //Writes out Class1
          MyInterface myInterfaceObject = (MyInterface) o;
          myInterfaceObject.WriteAnotherLine();
     }
}

I keep getting an invalid type cast exception.
0
 
LVL 17

Accepted Solution

by:
Jesse Houwing earned 2000 total points
ID: 13761427
on this line: MyInterface myInterfaceObject = (MyInterface) o; ??

did you try looking with the debugger what the actual type of o is?

I looked in my own code and found that I used a sytax that is a little different to perform the cast, but it should do exactly the same:

DataSet ds = type.GetConstructor(arr).Invoke((object[])arr) as DataSet;

is what I use
0
 

Author Comment

by:ktola
ID: 13761526
The single line of code worked!!!  You rock - thanks for all of the help!

One last thing - the "Invoke(new object[] {})" - if I wanted to pass in parameters, I assume that this is the place to put them in?

For example, if the method was WriteAnotherLine(string param1, string param2), I would write:

Invoke(new object["first value", "second value"] {})

Is that correct?  And thanks again.
0
 
LVL 17

Expert Comment

by:Jesse Houwing
ID: 13761899
You only need to add these in order to call a constructor that has parameters

thisType.GetConstructor(new Type[] {});

line to:

thisType.GetConstructor(new Type[] {typeof(string), typeof(string)});



Because you're using an interface you can just add that method signiature to the interface and call it with two parameters:

public interface MyInterface
{
     void WriteAnotherLine(string a, string b);
}

public class Class1 : MyInterface
{
     public Class1() {}
     public void WriteAnotherLine(string a, string b)
     {
          Console.WriteLine(a + " " + b);
     }
}

In a seperate project (e.g. different assembly) with a reference to the first assembly (for the Interface), I have the following pertinent code:

thisAssembly = Assembly.LoadFile("FILE_LOCATION");
Console.WriteLine(thisAssembly.FullName);          //This pulls up the correct DLL
Type[] theseTypes = thisAssembly.GetTypes();
Hashtable objects = new Hashtable(theseTypes.Length);
foreach(Type thisType in theseTypes)
{
     ConstructorInfo ci = thisType.GetConstructor(new Type[] {});
     object o = ci.Invoke(new object[] {});
     if(o != null)
     {
          Console.WriteLine(thisType.Fullname);          //Writes out Class1
          MyInterface myInterfaceObject = (MyInterface) o;
          myInterfaceObject.WriteAnotherLine("test", "me");
     }
}
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses
Course of the Month16 days, 14 hours left to enroll

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question