I've scanned many topics on this site, searched the internet, and experimented with code and nothing has worked. Most people are using separate projects or assemblies which I am not, it's a custom class that exists in the same project and same namespace. If I build the object manually by hard coding it in it works fine but I don't want to do that.
It's a C# ASPX project and I am debugging on IIS from Visual Studio (so maybe that's the issue?).
Type type = Type.GetType("<namespace>."+classname);
Object obj = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod(function);
response = (<cast object>)(methodInfo.Invoke(obj, null));
I am aiming for variable code where I can write plugins that will be dynamically instantiated. Type.GetType always returns null.
In almost all cases type returns null or when I switch it up with other code I'll get other errors thrown about not finding file or assembly and other errors like this class just doesn't exist...
What do I have to do to be able to build an object dynamically off a string? Let's say I have a class called "Foobar" and I want to do this,
string classname = "Foobar";
Object foobar = new classname(); //easy in PHP, nightmare in C#
Any help would be great, thanks. And before you tell me just to reference another post, I have referenced many and still have no success so if it's not the code than maybe it's how I'm debugging in a browser on IIS?
Type.GetType(String) accepts assembly-qualified type name.
See Type.AssemblyQualifiedName Property
You need to get the type from the assembly is was defined in:
typeof(SomeTypeInAssembly).Assembly.GetType("Namespace.Type")
If it is in the same namespace and assembly as the current object as you say, you should just be able to do the following to get hold of the Type you require:
Type type = Type.GetType(this.GetType().Namespace + "." + classname);
The rest should work as you have it.
Thanks for the suggestions, final code I ended up with below from the suggestions and other post I found on this site.
string fullname = string.Format("{0}.{1}", this.GetType().Namespace, classname);
Type type = Type.GetType(fullname,true);
Baseclass class = (BaseClass)Activator.CreateInstance(type,<parameter1>,...);
MethodInfo methodInfo = type.GetMethod("<method>");
methodInfo.Invoke(class, null);
You can store the return (may need casting) if you want to deal with the return type. Hope this helps someone if they're having issues like me.
Thanks to Rhumborl post, I guess it was an issue in just how I was originally trying to call the Type.GetType function.
String is a native type , witch is automatically inherited from object , since every type (aka class) is an object, so there is no need to do such a thing
Related
I have an abstract class and I want to initalize it to a class that extends it.
I have the child classes name as a string.
Besides this...
String childClassString;
MyAbstractClass myObject;
if (childClassString = "myExtenedObjectA")
myObject = new ExtenedObjectA();
if (childClassString = "myExtenedObjectB")
myObject = new ExtenedObjectB();
How can I do this? Basically how do I get rid of the if statements here?
Look at Activator.CreateInstance().
myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");
or
var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
I believe this should work:
myObject = (MyAbstractClass)Activator.CreateInstance(null, childClassString);
The null in the first parameter defaults to the current executing assembly. For more reference: MSDN
edit: forgot to cast to MyAbstractClass
I had some difficulty implementing some of the answers here because I was trying to instantiate an object from a different assembly (but in the same solution). So I thought I'd post what I found to work.
First, the Activator.CreateInstance method has several overloads. If you just call Activator.CreateInstance(Type.GetType("MyObj")), that assumes the object is defined in the current assembly, and it returns a MyObj.
If you call it as recommended in the answers here: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), then it instead returns an ObjectHandle, and you need to call Unwrap() on it to get your object. This overload is useful when trying to call a method defined in a different assembly (BTW, you can use this overload in the current assembly, just leave the AssemblyName parameter null).
Now, I found that the suggestion above to use typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName for AssemblyName actually gave me errors, and I could not get that to work. I'd get System.IO.FileLoadException (could not load file or assembly...).
What I did get to work is as follows:
var container = Activator.CreateInstance(#"AssemblyName",#"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
I have a C# function that makes a call to an API. This function returns an untyped object because of reasons.
Now, what I want to do is to cast that object to its actual type. I know what the type is called, but that's about it. Specifically, I can't cast it because I do not know which class I have to import.
So, what I would like to do is this:
object drawing = DrawingSoapLoader.GetDrawing(ITEM_NUMBER, REVISION_CODE, DRAWING_TYPE);
if(drawing is CADDrawing){
CADDrawing cadDrawing = (CADDrawing) drawing;
[...]
}
...however, that does not work because the type CADDrawing is not recognized.
Currently, what I have working instead is this:
object drawing = DrawingSoapLoader.GetDrawing(ITEM_NUMBER, REVISION_CODE, DRAWING_TYPE);
Type type = drawing.GetType();
Assert.AreEqual("CADDrawing", type.Name);
By debugging this, I can see that the type is this:
Name = "CADDrawing"
FullName = "CADDrawing"
Assembly = {gd5rgwpt, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly {System.Reflection.RuntimeAssembly}
I've also confirmed that the assembly code (here "gd5rgwpt") is different every time I run this.
I can find that .dll in my \AppData\Local\Temp folder, and I can even see that it has the CADDrawing type inside, and while I suppose I could just copy that .dll and manually add it to my project, somehow I don't think this is the right way to go about this.
Is there a better way to go about this?
Or is this just a case where it would be better to create a local CADDrawing class and then cast it to that?
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".
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".
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".