Dynamically Create a generic type for template
What you are looking for is MakeGenericType
string elementTypeName = Console.ReadLine();
Type elementType = Type.GetType(elementTypeName);
Type[] types = new Type[] { elementType };
Type listType = typeof(List<>);
Type genericType = listType.MakeGenericType(types);
IProxy proxy = (IProxy)Activator.CreateInstance(genericType);
So what you are doing is getting the type-definition of the generic "template" class, then building a specialization of the type using your runtime-driving types.
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.
How to dynamically create generic C# object using reflection?
Check out this article and this simple example. Quick translation of same to your classes ...
var d1 = typeof(Task<>);
Type[] typeArgs = { typeof(Item) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Per your edit: For that case, you can do this ...
var d1 = Type.GetType("GenericTest.TaskA`1"); // GenericTest was my namespace, add yours
Type[] typeArgs = { typeof(Item) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
To see where I came up with backtick1 for the name of the generic class, see this article.
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type type = typeof(IReadOnlyDictionary<,>);
Pass dynamically type to generic template
Lets say CreateManager<T>
is a method of type Foo
:
public class Foo
{
private void CreateManager<T>(ServiceProvider serviceProvider,
DeviceCapability deviceCapability)
{
}
}
In order to dynamically invoke the generic method, you'll need to get the MethodInfo
first, then call MakeGenericMethod
with the actual type you want to pass (I choose string
for the example)
var foo = new Foo();
var createManagerMethod = foo.GetType()
.GetMethod("CreateManager",
BindingFlags.Instance | BindingFlags.NonPublic);
var method = createManagerMethod.MakeGenericMethod(typeof(string));
method.Invoke(foo, new object[] { new ServiceProvider(), new DeviceCapability() });
Finally, call Invoke
with the proper object instance and parameters.
Declare a generic type instance dynamically
If you don't know the type at compile-time, but you want the actual type (i.e. not List<object>
) and you're not in a generic method/type with the appropriate type parameter, then you have to use reflection.
To make the reflection simpler, I've sometimes introduced a new generic type or method in my own code, so I can call that by reflection but then just use normal generics after that. For example:
object x = GetObjectFromSomewhere();
// I want to create a List<?> containing the existing
// object, but strongly typed to the "right" type depending
// on the type of the value of x
MethodInfo method = GetType().GetMethod("BuildListHelper");
method = method.MakeGenericMethod(new Type[] { x.GetType() });
object list = method.Invoke(this, new object[] { x });
// Later
public IList<T> BuildListHelper<T>(T item)
{
List<T> list = new List<T>();
list.Add(item);
return list;
}
Of course, you can't do an awful lot with the list afterwards if you don't know the type... that's why this kind of thing often falls down. Not always though - I've used something like the above on a few occasions, where the type system just doesn't quite let me express everything I need to statically.
EDIT: Note that although I'm calling Type.GetMethod in the code above, if you were going to execute it a lot you'd probably want to just call it once - after all, the method isn't going to change. You may be able to make it static (you could in the case above) and you probably want to make it private too. I left it as a public instance method for the simplicity of the GetMethod call in sample code - you'd need to specify the appropriate binding flags otherwise.
Passing an instance of a dynamic type to a generic method in a generic class
To answer your question:
var type = typeof(abc);
object instanceToModify = new abc();
var typeToCreate = typeof(GenericClass<>).MakeGenericType(type);
var methodToCall = typeToCreate.GetMethod("GenericMethod");
var genericClassInstance = Activator.CreateInstance(typeToCreate);
methodToCall.Invoke(genericClassInstance, new[] { instanceToModify });
DEMO
But:
If your type is only known at runtime your instance must be handled in a variable declared as object
or dynamic
. In that case you can change your method signature to:
public object GenericMethod(object obj)
{
// modify the object in some (arbitrary) way
IEnumerable<FieldInfo> fields = obj.GetType().GetRuntimeFields();
foreach (var field in fields)
{
if (field.FieldType == typeof(string))
{
field.SetValue(obj, "This field's string value was modified");
}
}
return obj;
}
There's no need for a generic class/method.
How can i create generic dynamic array?
I figured it out;
template<class T>
class List {
private:
T* first_cell = nullptr;
int size = 0; // currently occupied elements
int capacity = 8; // size of the allocated memory
public:
List() {
first_cell = new T[capacity]; // Declare the array in memory
}
List(const List& src)
: size(src.size),
capacity(src.capacity)
{
first_cell = new T[capacity];
std::copy_n(src.first_cell, size, first_cell);
}
List(List&& src)
: first_cell(src.first_cell),
size(src.size),
capacity(src.capacity)
{
src.first_cell = nullptr;
src.size = src.capacity = 0;
}
~List() {
delete[] first_cell;
}
List& operator=(List rhs) {
List temp(std::move(rhs));
std::swap(first_cell, temp.first_cell);
std::swap(size, temp.size);
std::swap(capacity, temp.capacity);
return *this;
}
void push_back(int number) {
if (size == capacity) {
int new_cap = capacity * 2; // increased capacity
T* new_arr = new T[new_cap]; // new arr with new capacity
for (int k = 0; k < size; ++k) {
new_arr[k] = first_cell[k]; // copy data from frist array
}
delete[] first_cell; // remove first array
first_cell = new_arr;
capacity = new_cap;
}
first_cell[size] = number;
++size;
}
int length() {
return size;
}
int first_index_of(int number) {
for (int k = 0; k < size; k++) {
if (number == first_cell[k]) {
return k;
}
}
return -1;
}
void print(char symb) {
for (int k = 0; k < size; ++k) {
std::cout << first_cell[k] << symb;
}
}
};
Ninject: How To Dynamically Inject Generic Type into Bound Template Object
Of course this works, it's very simple:
foreach(Type genericType in repositoryTypes)
{
object tempRepository = WebManager.Get(typeof(IRepository).MakeGenericType(genericType));
//do stuff with tempRepository
}
But then it get's trickier. How will you use this object
? You'll need to use reflection. It's simpler to use it once than for every call. So we can adjust/write the code as follows:
internal class Foo
{
private static readonly MethodInfo DoStuffToRepositoryForMethod =
typeof(Foo).GetMethod(
"DoStuffToRepositoryFor",
BindingFlags.Instance | BindingFlags.NonPublic);
private readonly IResolutionRoot resolutionRoot;
public Foo(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public void DoStuffToRepositories(params Type[] entityTypes)
{
foreach (Type entityType in entityTypes)
{
MethodInfo doStuffMethod = DoStuffToRepositoryForMethod
.MakeGenericMethod(entityType);
doStuffMethod.Invoke(this, new object[0]);
}
}
private void DoStuffToRepositoryFor<T>()
{
var repository = this.resolutionRoot.Get<IRepository<T>>();
repository.DoSomething();
}
}
and just for reference, this is a test showing that it works:
public class Test
{
[Fact]
public void TestIt()
{
var kernel = new StandardKernel();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
var foo = kernel.Get<Foo>();
foo.DoStuffToRepositories(typeof(string), typeof(int));
}
}
Don't employ magic if you don't have to
But i think the more important question is: why do you want to do this?
How do you know the list of entity types and entities to do something for?
In most cases there's an alternative way which doesn't involve that much "magic".
Related Topics
How to Sync the Scrolling of Two Multiline Textboxes
Combine Two Linq Lambda Expressions
Nhibernate How to Query Against an Ilist<String> Property
Cannot Deserialize the Current JSON Array (E.G. [1,2,3])
Dynamically Create a Generic Type for Template
How to Get Dpi Scale for All Screens
Image.Fromstream() Method Returns Invalid Argument Exception
Set Item Focus in Listview Wpf
Capturing Process Output via Outputdatareceived Event
How to Inject an Attribute Using a Postsharp Attribute
Openxml Sdk Having Borders for Cell
C# Structs: Unassigned Local Variable