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 (6)

  1. Dean Harding says:

    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).

  2. leppie says:

    Its probably a versioning issue from referencing the wrong Class1.dll.

  3. ManishAgarwal says:

    Nopes, it is not versioning issue.

  4. shahzaib says:

    mere msn id main tabs add kro plz junejo_jaan@hotmail.com he hai id

  5. Jon E. Ronnenberg says:

    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();

    }

  6. Vishal says:

    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?