How to call this function with reflection method,Parameters are delegates and generics - c#

// this is code
public class Foo1Parent
{
}
public delegate void CallBack<T>(T arg1);
public delegate void CallBack();
public class Foo
{
public void openWindow<T>(CallBack<T> onWindowAwake) where T:Foo1Parent
{
Debug.Log("test");
onWindowAwake(T);
}
//I use reflection to call methods "openWindow"
public void openCWindow(CallBack onback, string dialogName)
{
Type t = Assembly.GetExecutingAssembly().GetType(dialogName);
MethodInfo meth1 = this.GetType().GetMethod("openWindow");
object[] obj = new object[] { null }
meth.Invoke(this, obj );
}
}
//
Blockquote
The parameters of a generic is CallBack onWindowAwake I don't know how to do it

It is unclear what the question here is but, from the looks of things you are asking:
How do I invoke the generic method openWindow using reflection?
If this is the question then what you need to do after you get the MethodInfo which has the generic definition of openWindow is to create a generic method using MakeGenericMethod
Example:
MethodInfo genericDefinition = this.GetType().GetMethod("openWindow");
MethodInfo genericMethod = genericDefinition.MakeGenericMethod(typeof(Foo1Parent));
object[] obj = new object[] { null };
genericMethod.Invoke(this, obj);
This is the only way you can invoke a generic method, it is not possible to invoke a definition because, it doesn't know what T is.

Related

How to create an instance of generic type whose constructor requires a delegate function parameter?

I need to use the following generic class and method ParseFrom() in it:
public sealed class MessageParser<T> : MessageParser where T : IMessage<T>
{
public MessageParser(Func<T> factory); //constructor
public T ParseFrom(byte[] data);
}
Now, I do not know the type of the parameter for this class at compile time, so I use type reflection and MakeGenericType() method to do that:
//Assuming itemInstance is given as input parameter
Type typeArgument = itemInstance.GetType();
Type genericClass = typeof(MessageParser<>);
var genericType = genericClass.MakeGenericType(typeArgument);
var instance = Activator.CreateInstance(genericType);
It gives me a runtime error: MessageParser<> does not have a parameterless constructor. But when I try to pass Func<T> factory as a parameter for CreateInstance():
var instance = Activator.CreateInstance(genericType, () => Activator.CreateInstance(typeArgument));
it gives me a compile error: Cannot convert lambda expression to type 'string' because it is not a delegate type. Am I using the wrong syntax for a delegate function here?
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>());
}
}
To create the Func<T> through reflection, CreateDelegate is the way to go. Therefore a method, that has the expected signature - including the type contraints (T is IMessage<T>)- is needed.
Here's how you can get it work.
A downside is, that you will still need to use reflection to invoke the parser's methods, at least those that work with the type parameter:
public class CreateParserLateBound {
//The method with the matching signature
public static T MessageParserFactory<T>()
where T : IMessage<T>
{
//your factory code, you pass to MessageParser(Func<T> factory) goes here...
return default(T);
}
...
// itemInstance == item that is IMesage<T>, with T unknown at compiletime;
var itemType = itemInstance.GetType();
var boundParserType = typeof(MessageParser<>).MakeGenericType(itemType);
var boundFuncType = typeof(Func<>).MakeGenericType(itemType);
var factoryMethodInstance = typeof(CreateParserLateBound )
.GetMethod("MessageParserFactory")
.MakeGenericMethod(itemType)
.CreateDelegate(boundFuncType);
var parserInstance = Activator.CreateInstance(boundParserType,
new object[]{ factoryMethodInstance } );
//Invoke ParseFrom (also through reflection)
byte[] data = {1,2,3,4};
boundParserType.InvokeMember("ParseFrom",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null,
parserInstance, new object[] {data});
Full runnable code # https://dotnetfiddle.net/RIOEXA
The easy answer is to write your own generic method, then call that via reflection.
public static class Foo
{
public static MessageParser<T> CreateParser<T>() where T : IMessage<T>, new()
=> new MessageParser<T>(() => new T());
private static MethodInfo _createMethod = typeof(Foo)
.GetMethods()
.Where(m => m.Name == nameof(CreateParser) && m.IsGenericMethod)
.Single();
public static MessageParser CreateParser(Type type)
=> (MessageParser)_createMethod.MakeGenericMethod(type)
.Invoke(null, new object[] { });
}

Pass dynamically type to generic template

I am facing an issue with the reflection in C#. I need to construct a generic method that instantiate a class type dynamically with reflection. What I tried is the following.
Type myClass = Type.GetType(deviceBehavior.#class);
Type myInterfaceClass = myClass.GetInterface(deviceBehavior.#interface);
if (typeof (AnotherInterface).IsAssignableFrom(interfaceClass))
{
CreateManager<interfaceClass>(serviceProvider, deviceCapability);
}
My CreateManager method is as following:
private void CreateManager<T>(ServiceProvider serviceProvider, DeviceCapability deviceCapability)
{
T instanceToCreate = CreateClass<T>(serviceProvider, deviceCapability);
//Code to instantiate my class
}
The problem is that I can't call
CreateManager(serviceProvider, deviceCapability);
How can I pass an interface to my generic type? I searched and I couldn't find anything that I could understand clearly. i.e.
Calling a static method on a generic type parameter
Pass An Instantiated System.Type as a Type Parameter for a Generic Class
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.
I don't see, why you need reflection for this. You could do it like shown below
public interface IYourInterface //Give it a good name
{
void Instantiate(ServiceProvider serviceProvider, DeviceCapability deviceCapability);
}
public class YourClass : IYourInterface
{
public YourClass()
{
// do something if you want
}
public void Instantiate (ServiceProvider serviceProvider, DeviceCapability deviceCapability)
{
// what ever needs to be done here
}
}
private void CreateManager<T>(ServiceProvider serviceProvider, DeviceCapability deviceCapability)
where T : IYourInterface, new()
{
var instance = new T();
instance.Instantiate(serviceProvider, deviceCapability);
}
/*
Usage
*/
CreateManager<YourClass>(serviceProvider, deviceCapability);

Generic class instance with type from PropertyInfo.PropertyType

I have classes like below:
public class SampleClassToTest<T>
{
public static Fake<T> SomeMethod(string parameter)
{
// some code
}
public static Fake<T> SomeMethod(string parameter, int anotherParameter)
{
//some another code
}
}
public class Fake<T>
{
// some code
}
And I want to use them in this way:
SampleClassToTest<MyClass>.SomeMethod("some parameter");
The problem which I have is the following: type of "MyClass" I can get only from PropertyInfo instance using Reflection, so I have
Type propertyType = propertyInfo.PropertyType;
How can I do this? Any ideas?
UPD. I'm trying to pass the Type to generic method. And yes, this is what I want.
You would need to do:
typeof(SampleClassToTest<>).MakeGenericType(propertyType)
.GetMethod("SomeMethod", new Type[] {typeof(string)})
.Invoke(null, new object[] {"some parameter"});
Ugly.
If it can at all be helped, I would advise offering a non-generic API that accepts a Type instance; the nice thing here is that a generic API can call into a non-generic API trivially by using typeof(T).
It looks like you want:
Type propertyType;
Type classType = typeof(SampleClassToTest<>).MakeGenericType(propertyType);
MethodInfo method = classType.GetMethod("SomeMethod", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null);
object fake = method.Invoke(null, new object[] { "some parameter" });

Returning System.Action from static method on generic type with types defined at runtime

Below is a very paired down example of what I am trying to achieve
public class CoolClass<T>
{
public static void DoSomethingCool()
{
// Insert cool generic stuff here.
List<T> coolList = new List<T>();
}
}
public class OtherClass
{
public Action ReturnActionBasedOnStaticGenericMethodForType(Type type)
{
// Ideally this would just be
return CoolClass<type **insert magic**>.DoSomethingCool
}
}
I know if the type is known I can do following and it will return System.Action
return CoolClass<string>.DoSomethingCool
I know if all I wanted to do was invoke the method I can do
Type baseType = typeof(CoolClass<>);
Type[] typeArguments = new [] {type}
Type constructedType = baseType.MakeGenericType(typeArguments);
MethodInfo method = constructedType.GetMethod("DoSomethingCool");
method.Invoke(null,null);
I maybe down the wrong path all together. It seems like I am trying go get method to be a reference to DoSomethingCool method. I am wishing for something like (Action) method.
You're nearly there - you just need Delegate.CreateDelegate:
Action action = (Action) Delegate.CreateDelegate(typeof(action), null, method);

Conver Type class to a generic argument

Lets say I have a function
public void func1<T>();
And another function:
public void func2(Type type);
Inside func2, I want to call func1 with type. how can I "Convert" the type so it can fit in?
edit:
I didn't thought it will matter, but func1 is not my function. it part of the framework:
context.CreateObjectSet<T>()
You cannot call the generic function explicitly because you do not know the type at compile time. You can use reflections to call func1 and specify your type as generic argument. However I would advise you to change the signature of the methods to avoid using reflections if possible.
Here is an example of how to do it with Reflections:
private static void Method1(Type type)
{
MethodInfo methodInfo = typeof(Program).GetMethod("Method2", BindingFlags.NonPublic | BindingFlags.Static);
MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(type);
genericMethodInfo.Invoke(null, null);
}
private static void Method2<T>()
{
Console.WriteLine(typeof(T).FullName);
}
You would have to use reflection.
public void func2(Type type)
{
// call func1<T>()
var thisType = this.GetType();
var method = thisType.GetMethod("func1", new Type[0]).MakeGenericMethod(type);
method.Invoke(this, null);
}
Another option, of course: you can simply go the other direction and make the Type version the "real" one:
public T func1<T>()
{
func2(typeof(T));
}
public object func2(Type type)
{
Console.WriteLine(type.FullName);
}
This is similar to how the framework implements Enum.TryParse<TEnum> and Enum.TryParseEnum. The implementation of the generic TEnum variant simply passes it along (via typeof(TEnum)) to the non-generic (Type-based) method.

Categories

Resources