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?