How do I create a generic class from a string in C#?
Here is my 2 cents:
Type genericType = typeof(Repository<>);
Type[] typeArgs = { Type.GetType("TypeRepository") };
Type repositoryType = genericType.MakeGenericType(typeArgs);
object repository = Activator.CreateInstance(repositoryType);
Answering the question in comment.
MethodInfo genericMethod = repositoryType.GetMethod("GetMeSomething");
MethidInfo closedMethod = genericMethod.MakeGenericMethod(typeof(Something));
closedMethod.Invoke(repository, new[] { "Query String" });
How to use string as generic type
Take a look at Type.GetType(string)
:
string name = GetClassName();
Type klass = Type.GetType("Namespace." + name); // Replace "Namespace." with all the namespaces the classes live in, as the argument to `Type.GetType()` should be a fully-qualified name
if (klass is null)
{
// Class was not found
}
Of course, you also need to create an instance of Generic<klass>
:
Type genericOfKlass = typeof(Generic<>).MakeGenericType(klass);
Then instantiate it:
object instance = Activator.CreateInstance(genericOfKlass);
Then call .DoSomething()
on it:
MethodInfo doSomething = genericOfKlass.GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Instance);
doSomething.Invoke(instance, new object[] { });
As you can see, reflection (this kind of dynamic programming is called reflection) is not easy, but possible in .NET.
Edit: Complete example with request data:
Request request = GetClientRequst();
//container is IContainer of Autofac.
Type requestType = Type.GetType("Namespace." + requestType); // Replace "Namespace." with all the namespaces the classes live in, as the argument to `Type.GetType()` should be a fully-qualified name
Type entityDao = typeof(EntityDao<>).MakeGenericType(requestType);
MethodInfo containerResolve = container.GetType().GetMethod("Resolve");
MethodInfo genericContainerResolve = containerResolve.MakeGenericMethod(entityDao);
object resolveResult = genericContainerResolve.Invoke(container, new object[] { });
MethodInfo create = resolveResult.GetType().GetMethod("Create");
create.Invoke(resolveResult, new object[] { request.Data });
Construct class using string name for generic parameter
Using the answer in ModiX's link applied to your code, should result in something like this:
Type genericType = typeof(Deserializer<>);
Type[] typeArgs = { Type.GetType("Person") };
Type deserializerType = genericType.MakeGenericType(typeArgs);
object deserializer = Activator.CreateInstance(deserializerType);
MethodInfo fromFileMethod = deserializerType.GetMethod("FromFile");
fromFileMethod.Invoke(deserializer, new[] { file });
The line
MethodInfo closedMethod = genericMethod.MakeGenericMethod(typeof(Something));
is used if your method is generic, in your case if it would look something like this:
Deserializer<T>.FromFile<T2>(...)
Create instance of class with generic type and call method of same generic type from string name of object at runtime
Your wrapper got the following signature:
public class MyClass<T> where T : class, new()
it basically says "T needs to be a class and have a default constructor". The interesting part is about the default constructor. It means that the class must have a constructor with no arguments.
It tells .NET that you can invoke:
var obj = new T();
So the first step is to do just that:
public class MyClass<T> where T : class, new()
{
public IList<T> MyMethod(Stream stream)
{
var data = new List<T>();
//this
var obj = new T();
return data;
}
}
next you wanted to invoke a method. That's done with the help of reflection.
A simple example is:
var obj = new T();
//get type information
var type = obj.GetType();
//find a public method named "DoStuff"
var method = type.GetMethod("DoStuff");
// It got one argument which is a string.
// .. so invoke instance **obj** with a string argument
method.Invoke(obj, new object[]{"a string argument"});
Update
I missed the important part:
I need to return my IList from the MyMethod() method based on the name of the object I'm passing in as a string.
If the type is declared in the same assembly as your executing code you can just pass the full type name like Some.Namespace.ClassName" to
Type.GetType()`:
var type = Type.GetType("Some.Namespace.ClassName");
var obj = Activator.CreateInstance(type);
If the class is declared in another assembly you need to specify it:
var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName");
var obj = Activator.CreateInstance(type);
The rest is pretty much the same.
If you only have the class name you can traverse the assembly to find the correct type:
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(x => x.Name == "YourName");
var obj = Activator.CreateInstance(type);
Instantiate a generic type from string
Like this typeof(GenericRouteHandler<>).MakeGenericType(typeof(MemberHandler));
Of course if you don't have the types you have to use Type.GetType(string)
to get the type instead of typeof
.
EDIT: Then you have to activate the type Activator.CreateInstance()
or invoke a contructor if know the signature myGenericType.GetConstructor(ctorArgsTypes).Invoke(ctorParams);
; it can be faster if cache the consturctors it can be faster then Activator.CreateInstance()
msdn
Generic type from string value
I figured it out, I used InvokeMember to access it. :)
typeHandler.InvokeMember("Handle", BindingFlags.InvokeMethod, null, handler, new[] { requestItem });
Create instance of generic class with dynamic generic type parameter
I found very simple solution to problem. There is no need to cast object
to specific type T
, just use dynamic
keyword instead of casting
Type myGeneric = typeof(MyComparer<>);
Type constructedClass = myGeneric.MakeGenericType(T);
object created = Activator.CreateInstance(constructedClass);
dynamic comparer = created; // No need to cast created object to T
and then I can use comparer normally to call its methods like:
return comparer.Equals(myResultAsT, correctResultAsT);
According to LueTm comments, it is probably possible to use reflection again and call comparer methods, but this solution looks much easier.
Related Topics
Reverse Sorted Dictionary in .Net
Removing Hidden Characters from Within Strings
Wpf Controls Needed to Build Chess Application
Regular Expression to Get the Src of Images in C#
What Does "Displayclass" Name Mean When Calling Lambda
Performing a Mouse Click Without Moving Cursor
Troubles Implementing Ienumerable<T>
How to Use Dependency Injection in a .Net Core Actionfilterattribute
Dictionary <String,String> Map to an Object Using Automapper
Custom Sort Logic in Orderby Using Linq
Mocking Static Methods Using Rhino.Mocks