c# Creating an unknown generic type at runtime
I think you're looking for the MakeGenericType
method:
// Assuming that Property.PropertyType is something like List<T>
Type elementType = Property.PropertyType.GetGenericArguments()[0];
Type repositoryType = typeof(GenericRepository<>).MakeGenericType(elementType);
var repository = Activator.CreateInstance(repositoryType);
Create generic repository of unknown type at run-time
Just declare your repository and UoW method with the necessary type constraint for BaseClass:
public interface IRepository<TEntity> where TEntity : BaseClass
...
public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseClass
...
public virtual IRepository<TEntity> Repository<TEntity>() where TEntity : BaseClass
and then you can do that:
unit_of_work.Repository<BaseClass>().Insert(<whatever>);
This works because of generic contravariance.
Create instance of an unknown generic class Type-object at runtime?
The most generic way I can think of is by loading the target action type by name where the number after the backtick (aka grave accent) represents the number of generic arguments you need.
Unfortunately Action<>
is found in a different assembly (mscorlib) to the other action types so it needs to be handled differently when using this approach.
public static Type GetActionDelegateType(params Type[] typeArgs)
{
var argCount = typeArgs.Length;
if (argCount == 0) return typeof (Action);
var defType = argCount == 1
? typeof (Action<>) //special case since it's found in mscorlib
: Type.GetType(string.Format("System.Action`{0}, {1}",
argCount,
typeof (Action).Assembly.FullName));
return defType.MakeGenericType(typeArgs);
}
You can see the above code in action using this test code:
for (var i = 0; i <= 4; i++)
{
var typeArgs = Enumerable.Repeat(typeof (string), i).ToArray();
Console.WriteLine(GetActionDelegateType(typeArgs));
}
Casting to unknown derived type at runtime?
This has to do with covariance and contravariance.
The reason the cast fails is that, if you were allowed to do what you are trying to do, you would be able to pass an incompatible type to your handler. For example, your approach would allow this:
ICommandHandler<Command> focusHandler = new FocusHandler();
Command closeCommand = new CloseCommand();
focusHandler.Handle(closeCommand);
One way to deal with types that are not known at compile time is to use reflection. You mentioned Provider.GetRequiredService
so I'm going to assume that you are using Microsoft.Extensions.DependencyInjection. You can do the following:
- Register all of your handlers as their actual types
- Use reflection to create the actual handler type from the actual command type
- Use that type to get the handler from DI
- Use reflection to call the handler
Register your handlers like this:
services.AddTransient<ICommandHandler<FocusCommand>, FocusHandler>();
services.AddTransient<ICommandHandler<CloseCommand>, CloseHandler>();
Implement your Invoke
method like this:
public void Invoke(Command command)
{
Type commandType = command.GetType();
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(commandType);
var handler = serviceProvider.GetService(handlerType);
var mi = handlerType.GetMethod("Handle", 0, new[] { commandType });
mi.Invoke(handler, new[] { command });
}
How to create an instance of generic type whose constructor requires a delegate function parameter?
Constructing a delegate of an unknown type dynamically isn't as easy as using reflection to call a method, so the easiest option is to just write a statically typed method to construct the delegate, and then just call it using reflection.
public class DelegateCreator
{
public static Func<T> MakeConstructorStatically<T>()
{
return Activator.CreateInstance<T>;
}
public static object MakeConstructorDynamically(Type type)
{
return typeof(DelegateCreator)
.GetMethod(nameof(MakeConstructorStatically))
.MakeGenericMethod(type)
.Invoke(null, Array.Empty<object>());
}
}
How do you call a generic method if you only know the type parameter at runtime?
You need to call it using reflection:
var method = typeof(SomeClass).GetMethod("SomeMethod");
method.MakeGenericMethod(someType).Invoke(...);
How to cast to unknown generic runtime type (C# ChangeType equivalent)
In the declaration of your State
class, you forgot to specify the generic parameter of the widget.
Instead of:
class _PagedScrollerState<T> extends State<PagedScroller> {
do:
class _PagedScrollerState<T> extends State<PagedScroller<T>> {
Create instance of an unknown generic class Type-object at runtime?
The most generic way I can think of is by loading the target action type by name where the number after the backtick (aka grave accent) represents the number of generic arguments you need.
Unfortunately Action<>
is found in a different assembly (mscorlib) to the other action types so it needs to be handled differently when using this approach.
public static Type GetActionDelegateType(params Type[] typeArgs)
{
var argCount = typeArgs.Length;
if (argCount == 0) return typeof (Action);
var defType = argCount == 1
? typeof (Action<>) //special case since it's found in mscorlib
: Type.GetType(string.Format("System.Action`{0}, {1}",
argCount,
typeof (Action).Assembly.FullName));
return defType.MakeGenericType(typeArgs);
}
You can see the above code in action using this test code:
for (var i = 0; i <= 4; i++)
{
var typeArgs = Enumerable.Repeat(typeof (string), i).ToArray();
Console.WriteLine(GetActionDelegateType(typeArgs));
}
call a generic method with an object of an unknown type
You are only calling ToString
on the key and value, so simply have this method take an IDictionary
(non-generic), you are not using anything in there that is type-specific to T
or U
.
You can then simply cast all arguments to IDictionary
:
var d = arg as IDictionary;
if (d != null)
{
var res = DictionaryToString(d);
}
You may also need to amend the DictionaryToString
implementation:
static string DictionaryToString(IDictionary d)
{
var vals = new List<string>();
foreach (DictionaryEntry de in d)
{
vals.Add(de.Key.ToString() + ": " + de.Value.ToString());
}
return String.Join("\n", vals);
}
Alternatively, if you really want to use LINQ, you could try casting to dynamic
(it isn't possible to cast to anything else as this could be a generic dictionary (KeyValuePair<>
) or non-generic hashtable (DictionaryEntry
)):
var valueStrings = d.Cast<dynamic>().Select(de => de.Key.ToString() + ": " + de.Value.ToString());
return string.Join("\n", valueStrings);
This basically "duck types" the existence of the Key
and Value
properties.
Related Topics
Datagridview: How to Set a Cell in Editing Mode
Is the Size of a Form in Visual Studio Designer Limited to Screen Resolution
How to Get the Path of the Current User's "Application Data" Folder
C# Object Initialization of Read Only Collection Properties
Crud Operations Using Datagridview, Datatable and Dataadapter - Cannot Add New Row to Datagridview
Restsharp Simple Complete Example
Event Signature in .Net -- Using a Strong Typed 'Sender'
Display Hourglass When Application Is Busy
Format Decimal for Percentage Values
How to Force My C# Winforms Program Run as Administrator on Any Computer
Getting All Possible Combinations from a List of Numbers
Linq Query Built in Foreach Loop Always Takes Parameter Value from Last Iteration
Xml Deserialization of Collection Property with Code Defaults
Send Email via C# Through Google Apps Account
: ? Operators Instead of If|Else
Best Hashing Algorithm in Terms of Hash Collisions and Performance for Strings