Use the "new" keyword to create an object using reflection - c#

I'm completely new to reflection and I'm trying to call a class name from a db record and then load the class and run it but I'm pulling my hair out on where I'm going wrong, its probably something really silly I'm missing.
As an example I have my class in a different project and scripts folder, then call the name of it from the db record.
className = String.Format("Utilities.Scripts.{0}", script.ScriptClass);
Then in my main program I have
// Get a type from the string
Type type = Type.GetType(className);
// Create an instance of that type
Object obj = Activator.CreateInstance(type);
// Retrieve the method you are looking for
MethodInfo methodInfo = type.GetMethod("start");
// Invoke the method on the instance we created above
methodInfo.Invoke(obj, null);
But I am getting the error as when debugging I can see my details passed into the GetType(className) but nothing goes through to the type and as such into the obj where it is erroring.

You need to supply the Assembly Qualified Name of the type (as mentioned here) since the class is in a different project. Also, make sure that the assembly you are trying to load the type from is either in the same folder as the assembly trying to load it, or in the GAC.
For a class defined as below:
namespace Foo.Bar
{
public class Class1
{
}
}
The full class name is Foo.Bar.Class1. The assembly qualified name also specifies the full name of the assembly, as in Foo.Bar.Class1, Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35. You can find the Assembly Qualified Name of your type with somthing like:
Console.WriteLine(typeof(Foo.Bar.Class1).AssemblyQualifiedName)

The problem is in this line:
Type type = Type.GetType(className);
In that this particular overload of the method will not throw an exception when the type cannot be resolved. Instead use this overload which takes 2 booleans, one of which being throwOnError. Pass true for this parameter and you will get an exception which should help you debug why your type cannnot be resolved from the string you pass in.
I suspect you need a class name and assembly name
Utilities.Scripts.SomeClass, SomeAssemblyName

Related

Why does Type.GetType not return a Type when given an input the exact same as typof(X).GetFullName? [duplicate]

This code:
Type.GetType("namespace.a.b.ClassName")
returns null.
I have in the usings:
using namespace.a.b;
The type exists, it's in a different class library, and I need to get it by it's name given as string.
Type.GetType("namespace.qualified.TypeName") only works when the type is found in either mscorlib.dll or the currently executing assembly.
If neither of those things are true, you'll need an assembly-qualified name:
Type.GetType("namespace.qualified.TypeName, Assembly.Name")
You can also get the type without assembly qualified name but with the dll name also, for example:
Type myClassType = Type.GetType("TypeName,DllName");
I had the same situation and it worked for me. I needed an object of type "DataModel.QueueObject" and had a reference to "DataModel" so I got the type as follows:
Type type = Type.GetType("DataModel.QueueObject,DataModel");
The second string after the comma is the reference name (dll name).
Try this method.
public static Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null) return type;
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
type = a.GetType(typeName);
if (type != null)
return type;
}
return null;
}
If the assembly is part of the build of an ASP.NET application, you can use the BuildManager class:
using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
lock (typeCache) {
if (!typeCache.TryGetValue(typeName, out t)) {
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
t = a.GetType(typeName);
if (t != null)
break;
}
typeCache[typeName] = t; // perhaps null
}
}
return t != null;
}
if your class is not in current assambly you must give qualifiedName and this code shows how to get qualifiedname of class
string qualifiedName = typeof(YourClass).AssemblyQualifiedName;
and then you can get type with qualifiedName
Type elementType = Type.GetType(qualifiedName);
As Type.GetType(String) need the Type.AssemblyQualifiedName you should use Assembly.CreateQualifiedName(String, String).
string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);
The Version, Culture and PublicKeyToken are not required for assemblyName that's why you can use MyAssembly.GetName().Name.
About Type.GetType(String) :
If the type is in the currently executing
assembly or in Mscorlib.dll, it is sufficient to supply the type name
qualified by its namespace.
When I have only the class name I use this:
Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();
If it's a nested Type, you might be forgetting to transform a . to a +
Regardless, typeof( T).FullName will tell you what you should be saying
EDIT: BTW the usings (as I'm sure you know) are only directives to the compiler at compile time and cannot thus have any impact on the API call's success. (If you had project or assembly references, that could potentially have had influence - hence the information isnt useless, it just takes some filtering...)
I am opening user controls depending on what user controls the user have access to specified in a database. So I used this method to get the TypeName...
Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))
So now one can use the value returned in strType to create an instance of that object.
If the assembly is referenced and the Class visible :
typeof(namespace.a.b.ClassName)
GetType returns null because the type is not found, with typeof, the compiler may help you to find out the error.
Try using the full type name that includes the assembly info, for example:
string typeName = #"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);
I had the same situation when I was using only the the namesspace.classname to get the type of a class in a different assembly and it would not work. Only worked when I included the assembly info in my type string as shown above.
Make sure that the comma is directly after the fully qualified name
typeof(namespace.a.b.ClassName, AssemblyName)
As this wont work
typeof(namespace.a.b.ClassName ,AssemblyName)
I was stumped for a few days on this one
For me, a "+" was the key!
This is my class(it is a nested one) :
namespace PortalServices
{
public class PortalManagement : WebService
{
public class Merchant
{}
}
}
and this line of code worked:
Type type = Type.GetType("PortalServices.PortalManagement+Merchant");
This solution above seems to be the best to me, but it didn't work for me, so I did it as follows:
AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);
Type myType = Type.GetType(typeAssemblyQualifiedName);
The precondition is that you know the path of the assembly. In my case I know it because this is an assembly built from another internal project and its included in our project's bin folder.
In case it matters I am using Visual Studio 2013, my target .NET is 4.0. This is an ASP.NET project, so I am getting absolute path via HttpContext. However, absolute path is not a requirement as it seems from MSDN on AssemblyQualifiedNames
I cheated. Since the types I want to create (by name) are all in In a dll I control, I just put a static method in the dll in the assembly that takes a simple name, and calls type.GetType from that context and returns the result.
The original purpose was so that the type could be specified by name in configuration data. I've since change the code so that the user specified a format to process. The format handler classes implement a interface that determines if the type can parse the specified format. I then use reflection to find types that implement the interface, and find one that handles the format. So now the configuration specifies a format name, a not a specific type. The reflection code can look at adjacent dlls and load, them so I have a sort poor man's plug-in architecture.
Very late reply, but if anyone is dealing with this a decade later:
There is a very, very small chance that your class in Visual Studio has a Build Action set to "Content" instead of "Compile".
Click on your class in Solution Explorer, then look at the properties.
Check that Build Action is "Compile", not "Content".

Reflection C# - GetType() Returns Null [duplicate]

This code:
Type.GetType("namespace.a.b.ClassName")
returns null.
I have in the usings:
using namespace.a.b;
The type exists, it's in a different class library, and I need to get it by it's name given as string.
Type.GetType("namespace.qualified.TypeName") only works when the type is found in either mscorlib.dll or the currently executing assembly.
If neither of those things are true, you'll need an assembly-qualified name:
Type.GetType("namespace.qualified.TypeName, Assembly.Name")
You can also get the type without assembly qualified name but with the dll name also, for example:
Type myClassType = Type.GetType("TypeName,DllName");
I had the same situation and it worked for me. I needed an object of type "DataModel.QueueObject" and had a reference to "DataModel" so I got the type as follows:
Type type = Type.GetType("DataModel.QueueObject,DataModel");
The second string after the comma is the reference name (dll name).
Try this method.
public static Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null) return type;
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
type = a.GetType(typeName);
if (type != null)
return type;
}
return null;
}
If the assembly is part of the build of an ASP.NET application, you can use the BuildManager class:
using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
lock (typeCache) {
if (!typeCache.TryGetValue(typeName, out t)) {
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
t = a.GetType(typeName);
if (t != null)
break;
}
typeCache[typeName] = t; // perhaps null
}
}
return t != null;
}
if your class is not in current assambly you must give qualifiedName and this code shows how to get qualifiedname of class
string qualifiedName = typeof(YourClass).AssemblyQualifiedName;
and then you can get type with qualifiedName
Type elementType = Type.GetType(qualifiedName);
As Type.GetType(String) need the Type.AssemblyQualifiedName you should use Assembly.CreateQualifiedName(String, String).
string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);
The Version, Culture and PublicKeyToken are not required for assemblyName that's why you can use MyAssembly.GetName().Name.
About Type.GetType(String) :
If the type is in the currently executing
assembly or in Mscorlib.dll, it is sufficient to supply the type name
qualified by its namespace.
When I have only the class name I use this:
Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();
If it's a nested Type, you might be forgetting to transform a . to a +
Regardless, typeof( T).FullName will tell you what you should be saying
EDIT: BTW the usings (as I'm sure you know) are only directives to the compiler at compile time and cannot thus have any impact on the API call's success. (If you had project or assembly references, that could potentially have had influence - hence the information isnt useless, it just takes some filtering...)
I am opening user controls depending on what user controls the user have access to specified in a database. So I used this method to get the TypeName...
Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))
So now one can use the value returned in strType to create an instance of that object.
If the assembly is referenced and the Class visible :
typeof(namespace.a.b.ClassName)
GetType returns null because the type is not found, with typeof, the compiler may help you to find out the error.
Try using the full type name that includes the assembly info, for example:
string typeName = #"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);
I had the same situation when I was using only the the namesspace.classname to get the type of a class in a different assembly and it would not work. Only worked when I included the assembly info in my type string as shown above.
Make sure that the comma is directly after the fully qualified name
typeof(namespace.a.b.ClassName, AssemblyName)
As this wont work
typeof(namespace.a.b.ClassName ,AssemblyName)
I was stumped for a few days on this one
For me, a "+" was the key!
This is my class(it is a nested one) :
namespace PortalServices
{
public class PortalManagement : WebService
{
public class Merchant
{}
}
}
and this line of code worked:
Type type = Type.GetType("PortalServices.PortalManagement+Merchant");
This solution above seems to be the best to me, but it didn't work for me, so I did it as follows:
AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);
Type myType = Type.GetType(typeAssemblyQualifiedName);
The precondition is that you know the path of the assembly. In my case I know it because this is an assembly built from another internal project and its included in our project's bin folder.
In case it matters I am using Visual Studio 2013, my target .NET is 4.0. This is an ASP.NET project, so I am getting absolute path via HttpContext. However, absolute path is not a requirement as it seems from MSDN on AssemblyQualifiedNames
I cheated. Since the types I want to create (by name) are all in In a dll I control, I just put a static method in the dll in the assembly that takes a simple name, and calls type.GetType from that context and returns the result.
The original purpose was so that the type could be specified by name in configuration data. I've since change the code so that the user specified a format to process. The format handler classes implement a interface that determines if the type can parse the specified format. I then use reflection to find types that implement the interface, and find one that handles the format. So now the configuration specifies a format name, a not a specific type. The reflection code can look at adjacent dlls and load, them so I have a sort poor man's plug-in architecture.
Very late reply, but if anyone is dealing with this a decade later:
There is a very, very small chance that your class in Visual Studio has a Build Action set to "Content" instead of "Compile".
Click on your class in Solution Explorer, then look at the properties.
Check that Build Action is "Compile", not "Content".

loading assembly during run time concept

After loading an assembly, when instantiating it:
Assembly asm = Assembly.LoadFile(#"c:\file.dll");
Type type = asm.GetType("DLLTYPE");
object instance = Activator.CreateInstance(type);
How C# know the type?
From my logic, the dll should have header which define the object type.
so why is the DLLTYPE string for ?
How C# know the type?
You've passed it as parameter:
Type type = asm.GetType("DLLTYPE");
so why is the "DLLTYPE" string for ?
It's the namespace and the class name that you want to instantiate:
Namespace.ClassName
Be careful because this method will return null if you make a mistake in the typename. If you want to ensure that the type exists you could use the following overload:
Type type = asm.GetType("Namespace.ClassName", true);
This will throw an exception instead of returning null which will be easier to debug instead of the NRE you would otherwise get on the Activator.CreateInstance method.

Type.GetType("NameSpace.ClassName", false, true) returns null. What could be wrong?

I am trying to create instance of class by using reflection in ASP.net web site. Class ClassName is defined and located in App_code folder. Following line returns null, what could be wrong.
Type type = Type.GetType("NameSpace.ClassName", false, true);
Supplying only the type name works only in the following scenarios:
The type in question is in the currently executing assembly (i.e., the same assembly as your code)
OR
The type in question is in mscorlib.dll.
In all other cases, you have to supply the assembly-qualified name of the type. This is what allows it to locate the appropriate assembly and load it.
You can use System.Web.Compilation.BuildManager.GetType e.g.
using System.Web.Compilation;
Type t = BuildManager.GetType("NameSpace.ClassName", true);
Afin, try this. This is to piggyback on Adam Robinson's answer and to demonstrate what you need to do to test the statements made in the answer and the comments for yourself.
Type t = typeof(YourNamespace.YourClass);
string assemblyQualifiedName = t.AssemblyQualifiedName;
Type type = Type.GetType(assemblyQualifiedName, false, true);
// type will not be null
The assembly qualified name will be something like "Sample.Foo, App_Code.qwijwhsy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null".
Try using Assembly.GetType(), that should look in the referenced assembly. Of course, you'd need to load the appropriate Assembly class, which would be GetCallingAssembly() if the type shares assembly with your executing code, or something else otherwise, in which case you'd use one of the static LoadSomething() methods within the Assembly class.
For instance:
Type type = LoadFrom("App_code\ClassAssembly.dll").GetType("Namespace.ClassName");
// Load assembly, then type!
Type type2 = GetCallingAssembly().GetType("Namespace.ClassName");
// If it's the same assembly as the calling code.
Very simple code. I think that it doesn't need any explaining.
using System.Reflection;
Assembly assembly = Assembly.LoadFrom("MyLibrary.dll");
Type type = assembly.GetType("NameSpace.ClassName", false, true);
if its in App_Code try
Type t = Type.Get("Namespace.ClassName, __code");

Type.GetType("namespace.a.b.ClassName") returns null

This code:
Type.GetType("namespace.a.b.ClassName")
returns null.
I have in the usings:
using namespace.a.b;
The type exists, it's in a different class library, and I need to get it by it's name given as string.
Type.GetType("namespace.qualified.TypeName") only works when the type is found in either mscorlib.dll or the currently executing assembly.
If neither of those things are true, you'll need an assembly-qualified name:
Type.GetType("namespace.qualified.TypeName, Assembly.Name")
You can also get the type without assembly qualified name but with the dll name also, for example:
Type myClassType = Type.GetType("TypeName,DllName");
I had the same situation and it worked for me. I needed an object of type "DataModel.QueueObject" and had a reference to "DataModel" so I got the type as follows:
Type type = Type.GetType("DataModel.QueueObject,DataModel");
The second string after the comma is the reference name (dll name).
Try this method.
public static Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null) return type;
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
type = a.GetType(typeName);
if (type != null)
return type;
}
return null;
}
If the assembly is part of the build of an ASP.NET application, you can use the BuildManager class:
using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
lock (typeCache) {
if (!typeCache.TryGetValue(typeName, out t)) {
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
t = a.GetType(typeName);
if (t != null)
break;
}
typeCache[typeName] = t; // perhaps null
}
}
return t != null;
}
if your class is not in current assambly you must give qualifiedName and this code shows how to get qualifiedname of class
string qualifiedName = typeof(YourClass).AssemblyQualifiedName;
and then you can get type with qualifiedName
Type elementType = Type.GetType(qualifiedName);
As Type.GetType(String) need the Type.AssemblyQualifiedName you should use Assembly.CreateQualifiedName(String, String).
string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);
The Version, Culture and PublicKeyToken are not required for assemblyName that's why you can use MyAssembly.GetName().Name.
About Type.GetType(String) :
If the type is in the currently executing
assembly or in Mscorlib.dll, it is sufficient to supply the type name
qualified by its namespace.
When I have only the class name I use this:
Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();
If it's a nested Type, you might be forgetting to transform a . to a +
Regardless, typeof( T).FullName will tell you what you should be saying
EDIT: BTW the usings (as I'm sure you know) are only directives to the compiler at compile time and cannot thus have any impact on the API call's success. (If you had project or assembly references, that could potentially have had influence - hence the information isnt useless, it just takes some filtering...)
I am opening user controls depending on what user controls the user have access to specified in a database. So I used this method to get the TypeName...
Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))
So now one can use the value returned in strType to create an instance of that object.
If the assembly is referenced and the Class visible :
typeof(namespace.a.b.ClassName)
GetType returns null because the type is not found, with typeof, the compiler may help you to find out the error.
Try using the full type name that includes the assembly info, for example:
string typeName = #"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);
I had the same situation when I was using only the the namesspace.classname to get the type of a class in a different assembly and it would not work. Only worked when I included the assembly info in my type string as shown above.
Make sure that the comma is directly after the fully qualified name
typeof(namespace.a.b.ClassName, AssemblyName)
As this wont work
typeof(namespace.a.b.ClassName ,AssemblyName)
I was stumped for a few days on this one
For me, a "+" was the key!
This is my class(it is a nested one) :
namespace PortalServices
{
public class PortalManagement : WebService
{
public class Merchant
{}
}
}
and this line of code worked:
Type type = Type.GetType("PortalServices.PortalManagement+Merchant");
This solution above seems to be the best to me, but it didn't work for me, so I did it as follows:
AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);
Type myType = Type.GetType(typeAssemblyQualifiedName);
The precondition is that you know the path of the assembly. In my case I know it because this is an assembly built from another internal project and its included in our project's bin folder.
In case it matters I am using Visual Studio 2013, my target .NET is 4.0. This is an ASP.NET project, so I am getting absolute path via HttpContext. However, absolute path is not a requirement as it seems from MSDN on AssemblyQualifiedNames
I cheated. Since the types I want to create (by name) are all in In a dll I control, I just put a static method in the dll in the assembly that takes a simple name, and calls type.GetType from that context and returns the result.
The original purpose was so that the type could be specified by name in configuration data. I've since change the code so that the user specified a format to process. The format handler classes implement a interface that determines if the type can parse the specified format. I then use reflection to find types that implement the interface, and find one that handles the format. So now the configuration specifies a format name, a not a specific type. The reflection code can look at adjacent dlls and load, them so I have a sort poor man's plug-in architecture.
Very late reply, but if anyone is dealing with this a decade later:
There is a very, very small chance that your class in Visual Studio has a Build Action set to "Content" instead of "Compile".
Click on your class in Solution Explorer, then look at the properties.
Check that Build Action is "Compile", not "Content".

Categories

Resources