Issues in create the instance of singilton class using reflection in C#
Scenario -
I have a public class (named class1) with only internal constructors. Assume this class exists in assembly class1.dll. Now I want to create the instance of class1 inside another public class (named class2) that exist in another assembly (class2.exe).
Case A
Class1.dll
namespace ns1
{
public class class1 {
internal class1(int i)
{
Console.WriteLine("init ns1.Class1, args value: " + i);
}
public void print()
{
Console.WriteLine("executing ns1.class1.print()");
}
}
}
Class2.exe
namespace ns2
{
class Class2
{
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(@"c:\Class1.dll");
Type type = assembly.GetType("ns1.class1", true, true);
ConstructorInfo[] constructors = type.GetConstructors(
BindingFlags.NonPublic | BindingFlags.Instance);
object o = constructors[0].Invoke(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new object[] { 1 },
System.Globalization.CultureInfo.InvariantCulture);
// typecasting does not work
ns1.class1 instance = o as ns1.class1;
}
}
}
The type cast of object o to ns1.class1 fails. Program things that ns1.class1 defined in assembly loaded form c:\class1.dll is different that the one declared in the statement but they are exactly the same. Can anyone explain the reason? Is it because I am not using Binder?
Case B
Class1.dll
namespace ns1
{
public class class1:Stack {
internal class1(int i)
{
Console.WriteLine("init ns1.Class1, args value: " + i);
}
public void print()
{
Console.WriteLine("executing ns1.class1.print()");
}
}
}
Class2.exe
namespace ns2
{
class Class2
{
static void Main(string[] args)
{
Assembly assembly = Assembly.LoadFrom(@"c:\Class1.dll");
Type type = assembly.GetType("ns1.class1", true, true);
ConstructorInfo[] constructors = type.GetConstructors(
BindingFlags.NonPublic | BindingFlags.Instance);
object o = constructors[0].Invoke(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new object[] { 1 },
System.Globalization.CultureInfo.InvariantCulture);
// typecasting works
Stack instance = o as Stack;
MethodInfo[] methods = type.GetMethods();
methods[0].Invoke(o, null);
}
}
}
The type casting of object o to Stack works because the type is predefined and compiler has no issue is finding the standard definition or maybe binding works by default. I can even invoke print method on the object. Another interesting observation is that there is no object slicing happening in C# unlike C++. This is because the everything is passed by reference in C# (thanks to Abhinab who pointed out the reason).
Comments
- Anonymous
March 23, 2006
Why are you doing this:
Assembly assembly = Assembly.LoadFrom(@"c:Class1.dll");
Type type = assembly.GetType("ns1.class1", true, true);
? You already have the type, just do:
Type type = typeof(ns1.class1)
I'm pretty sure it's not working because you're loading the assembly for reflection using Assembly.LoadFrom (rather than Assembly.Load). - Anonymous
March 24, 2006
Its probably a versioning issue from referencing the wrong Class1.dll. - Anonymous
April 17, 2006
Nopes, it is not versioning issue. - Anonymous
April 26, 2006
mere msn id main tabs add kro plz junejo_jaan@hotmail.com he hai id - Anonymous
June 02, 2006
You have to give Class1 an interface you can type cast to. Class2 got to know the same Interface. That's how you map the two classes. In design patterns it's called a Bridge.
Code should be something like this:
Interface:
public interface IClass
{
void print();
}
// ---
Class1.dll:
public class class1 : IClass
{
... the rest of your code
}
// ---
Class2.dll
using IClass
... namespace
public class Class2
{
Assembly assembly = Assembly.LoadFrom(@"c:Class1.dll");
instance = (IClass) assembly.CreateInstance("class1");
instance.Print();
} - Anonymous
June 23, 2008
Dim theStream As New CILMEMFILESTREAMLib.CIMemFileStream Dim theIStream As CILTraceDebug.IStream theIStream = theStream (Also tried forcefull typecasting using CType,DirectCast etc.. but not working..) Both these are from different interop dlls but have same base class. Type casting between these two didnt worked. Can anybody suggest any workaround for this?