Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: reflection
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.
 
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.
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.
 
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.
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 13-Aug-12 19:48pm
3529255403
Edited 13-Aug-12 22:27pm
v2
Comments
Kenneth Haugland at 14-Aug-12 1:12am
   
Do you mean like this:
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx
?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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 :
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 :
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());
  Permalink  
v2
Comments
3529255 at 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 at 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 at 14-Aug-12 3:27am
   
I have provided with an example. Hoping for reply.
Mehdi Gholam at 14-Aug-12 3:43am
   
See the update.
3529255 at 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".
Mehdi Gholam at 14-Aug-12 4:04am
   
Like I said once you use reflection then it's reflection all the way. If you want to access your types in your methods like normal the the compiler must know the type definitions at compile time (stands to reason) hence you must add the references to your project.
 
[if you are using .net 4 look at dynamic types which do the binding at runtime].
3529255 at 14-Aug-12 4:15am
   
This is to confirm for the last time that "Adding references is mandatory". Is that what you are saying?.
 
If adding references of Type being reflected to the main project is the expected task then that answers my question. I thought reflection mechanism does not require references in what so ever scenarios.
 
Thanx.
Andreas Gieriet at 14-Aug-12 3:50am
   
See my Solution 3.
You either have all libraries together with the console application assembly in *one* folder or (advanced ;-)) you need to install an assembly and type resolution handler. Such a handler is the fallback if the .NET assembly resolution fails. But first try to get all assembies into one folder to show that Solution 3 is working for you.
Cheers
Andi
Mehdi Gholam at 14-Aug-12 4:01am
   
The presumption was that all the required files were beside the exe.
Andreas Gieriet at 14-Aug-12 4:04am
   
Yes, that was my understanding too. But if you do a VS2010 solution with all three projects in it, it will not work. See also my Solution 3 below.
Let's first make sure that we do not have *that* problem.
Cheers
Andi
3529255 at 14-Aug-12 4:17am
   
Like Mehdi said, adding references in the main project,that answers my questions. I am simply confused if it worked without adding the references.
 
Thanx.
Andreas Gieriet at 14-Aug-12 4:49am
   
It can work without adding references, depending what you do in your test runner.
A test runner does not know of any of its test classes that will be eventually passed to it. So, you can not add for each of your test classes a reference in the test runner. As a consequence, this also reduces the accessibility of your test types in you test runner. You probably do call your test methods from the test types via reflection too.
 
If so, your test runner project does not need any reference to any test type. You only must make sure that the test runner can access the assemblies at *run* *time*. This is given if the test assemblies are siblings to the test runner, or if the test runner has some assembly resolution handler installed so that it finds the assemblies elsewhere at run time.
 
An again: if you add a reference to the test runner, this also implies in Visual Studio, that the references assemblies get deployed beside the test runner. But this is useless for your situation if I understand that correctly.
Cheers
Andi
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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.
// 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
  Permalink  
Comments
3529255 at 14-Aug-12 3:28am
   
I have added an example. Could you please reply based on that scenario.
Thank you
Andreas Gieriet at 14-Aug-12 4:00am
   
See my Solution 3 below.
Cheers
Andi
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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.

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:

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

LibB:

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.
  Permalink  
v3

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

  Print Answers RSS
0 OriginalGriff 350
1 Jochen Arndt 190
2 Richard MacCutchan 135
3 Sergey Alexandrovich Kryukov 120
4 DamithSL 95
0 OriginalGriff 6,045
1 DamithSL 4,611
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,310


Advertise | Privacy | Mobile
Web04 | 2.8.141220.1 | Last Updated 14 Aug 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100