Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a console application and two class libraries say (A and B). I have class "a" in A and class "b" in B.
Obviously my entry poin of program will be the console application. In class "a",
I am loading the type of "b" through reflection.

C#
Type type = null;
            type = Type.GetType(a,A, version=..,token=) //assembly qualified name;
            object obj = Activator.CreateInstance(type);


Now my question is for the above code to work where do i need the reference of B. Do i need the reference of class library B in class library A or the console Application itself or I do not need it at all.

To make my scenario more specific, I am providing my sample example.
I have a class library named TestType. It has a single class named TypeA.
C#
namespace TestType
{
    public class TypeA
    {
        TypeA() { }
    }
}


Likewise I have another class library named TestApp in which Runner class is trying to create an object of TypeA through
reflection.

C#
namespace TestApp
{
    public static class Runner
    {
        public static void CreateInstance()
        {
            Type t = Type.GetType("TestType.TypeA, TestType, Version=1.0.0.0, Culture=neutral");
        }

    }
}



I have a console application to test the functionaly.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TestApp.Runner.CreateInstance();
        }
    }
}


Now when I run this, "Runner" returns NULL. But when I add reference of "TestType" in "ReflectionTest" then it works fine.
All I wanted to know is, why is it necessary to add the reference of type being reflected in the console application. Instead my assumption was "TestApp" would need the reference of "TestType" since it is the one which is returning the object of "TypeA".
Posted
Updated 13-Aug-12 21:27pm
v2
Comments
Kenneth Haugland 14-Aug-12 1:12am    
Do you mean like this:
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx
?

First when using Type.GetType() you have to supply the assembly qualified name as a string.

The .net loader will load all the types that needs to be loaded so you don't have to do anything.

An important note is when you use reflection then all your code will need to be using reflection for property and method access since the Activator returns an object not YourType so you can't do :
C#
object o = Activator.CreateInstance(type);
o.CallMyMethod(); // error


EDIT:
Type.GetType requires you to supply a fully qualified assembly name, it will not work with the full qualified type name, so do the following :
C#
string[] s = typestr.Split(new char{','},2); // typestr = "TestType.TypeA, TestType, Version=1.0.0.0, Culture=neutral"
object o = Activator.CreateInstance(s[0].Trim(), s[1].Trim());
 
Share this answer
 
v2
Comments
3529255 14-Aug-12 2:22am    
I am providing the assebly qualified name in the GetType() method.
In my case, the object of type "b" is created in "a" only when I put the reference of Assembly "B" in the console application.Othewise, it simply returns Null.

You said .net will load all the types that needs to be loaded. But in the above example for Assembly "A" to recognize "b" as the class of assembly "B", doesnt it have to have reference of "B".
Andreas Gieriet 14-Aug-12 2:31am    
I think you should provide an example of your code - just reduced to the max such that it shows your situation. How exactly is b related to a? Is b part of the public interface of a or is it even also created via reflection and only stored as object too, or...?
Cheers
Andi

[EDIT]No need to post your example - I did try it out myself - see Solution 3 for the results.[/EDIT]
3529255 14-Aug-12 3:27am    
I have provided with an example. Hoping for reply.
Mehdi Gholam 14-Aug-12 3:43am    
See the update.
3529255 14-Aug-12 3:59am    
Haha Mehdi, ok I got what you are trying to say. All i need to do is provide full qualified type name. But you are not getting what my point is. Even after providing full qualified type name, it only works if I add the reference of Type being reflected in my main test application. My question was "Why is it required to add reference in the test application".
I assume you did try it out and now you want a confirmation of your observation?

As long as you don't need any information from your loaded type (like calling a method or a property, etc.), you don't need any references anywhere.

But since in most cases you do need some information of that type, such a scenario is usually done via interfaces: that loaded type implements an interface and you cast the created object to that interfaces instead of an object. Then you only need to know the interface type (i.e. have the defining assembly references in the project).

E.g.
C#
// interface assembly I
public interface IMyPlugin
{
   string Name { get; }
   ...
}

// implementation A assembly: reference to assembly I
public class MyPluginA: IMyPlugin
{
   public string Name { get { return m_Name; } }
   ...
}

// main assembly: references only assembly I
...
Dictionary<string, IMyPlugin> m_Plugins = new Dictionary<string, IMyPlugin>();
...
foreach(Type type in LoadMyPluginConfig(...))
{
    IMyPlugin plugin = (IMyPlugin)Activator.CreateInstance(type);
    m_Plugins.Add(plugin.Name, plugin);
}
...

You may want to have a look at MEF (Managed Extensibility Framework)[^] to have this kind of activation done for you.

Cheers
Andi
 
Share this answer
 
Comments
3529255 14-Aug-12 3:28am    
I have added an example. Could you please reply based on that scenario.
Thank you
Andreas Gieriet 14-Aug-12 4:00am    
See my Solution 3 below.
Cheers
Andi
Now that I did try it out myself, I think I found the reason for your problem:
you get fooled by Visual Studio.

Visual Studio usually deploys (silently) all the project references to the build output folder of the given C# project. I.e. when you add in the main program project a reference to the LibA and LibB, then they get deployed beside the main program in the bin\Debug or bin\Release folder.

If you do not reference these two libs, you get only the main program assembly deployed to its bin\Debug or bin\Release folder.

What you observe is that the type from LibA can not be constructed since the types could not be found by .NET assembly resolution machinery.

Do the following:
1) set the output folder of all projects to ..\bin (instead of bin\Debug or bin\Release)
2) recompile the solution.

Now, all assemblies are in the same bin folder and .NET can resolve the needed types.

Cheers
Andi

PS: Example code:


Main Project, no references to neither LibA nor LibB.

C#
namespace ConsoleApplication9
{
    class Program
    {
        static void Main(string[] args)
        {
            Type type = Type.GetType("LibA.ClassA, LibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
            object obj = Activator.CreateInstance(type);
            Console.WriteLine(obj.ToString());
        }
    }
}



LibA with reference to LibB:

C#
namespace LibA
{
    public class ClassA
    {
        public ClassB Other { get; set; }
        public ClassA()
        {
            Other = new ClassB();
        }
    }
}



LibB:

C#
namespace LibB
{
    public class ClassB
    {
        public void Write(string message)
        {
            Console.WriteLine("Message: {0}", message);
        }
    }
}


Now, the important part is: build all projects such that the resulting assemblies are located in *one* directory.
This can be done by one of the following:

  1. the steps as described above
  2. copy the assemblies manually to one directory (crude)
  3. if you have a specific deployment structure in the product, implement an assembly resolution handler

I suggest to go the 1st approach since it is the simplest one. Otherwise, a resolution handler would help.
 
Share this answer
 
v3

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900