Reputation: 448
I've been trying to wrap my head around handling this scenario. The various similar (but not specifically the same) questions I've browsed on SO hasn't quite led me to where I'd like.
I have a situation where I have a Type
and an object of type Func<string, (bool, T)>
where T matches the Type
. I'd like to be able to, via reflection or other means, call its Invoke
method.
I have some Type
at runtime:
Type type;
I have the Func
in memory, but as an object
:
object func;
The underlying Type of func
is what I described earlier. For example, if type
represents DateTime
, then func
's underlying type would be:
Func<string, (bool, DateTime)>
But type
can be anything at runtime, so if it was instead an int
, then func
would now be a
Func<string, (bool, int)>
How can I use the fact that I have the correct type at runtime, to invoke my func? I'm assuming I have to use reflection of some sort but don't really understand it well enough to get started.
Any help is greatly appreciated.
I'm pretty new to reflection in general but I'm finding it very interesting and pretty difficult for some things. If you have any recommendations on readings or any other tips on how to better learn about reflection that'd be sweet as well!
EDIT/UPDATE after some more thought:
Would it be better just to use dynamic
and call Invoke that way? Seems like it would work fine, but then that raises the question, of why you would ever go through the more difficult or longer process of setting up reflection to invoke something, instead of a simply dynamic call.
In any case, I'd still like to know how this would work using reflection, would be interesting to see
Upvotes: 3
Views: 1283
Reputation: 111930
The problem is wrong and "artificial". Yes, you can use reflection, yes, you can use dynamic... But the "right" thing to do would be to change the signature to:
public (bool, object) SomeMethod(string par)
delegate:
Func<string, (bool, object)>
or
public bool SomeMethod(string par, out object obj)
delegate (note that you can't use Func<,>
/Action<,>
):
public delegate bool MyDelegate(string par, out object obj)
With this signature you don't need reflection to call the method and you don't need reflection to parse the return. Your return value/out
is boxed by the method inside the object
. The performance is still better than using reflection.
Other semi-good candidate could be:
Tuple<bool, type> SomeMethod(string par)
(where type
is your changing type)
delegate:
Func<string, object>
or
Func<string, dynamic>
By using a Tuple<bool, type>
you gain something: Tuple<>
is a reference type, and delegates are contravariant in the return type, so you can "unify" them to object
/dynamic
(dynamic
is an object
with some information to the C# compiler that the programmer will try to do "bad things" to the object
)
Now you'll have to use reflection/dynamic
to access the Tuple<>.Item1
and Tuple<>.Item2
.
The difference between using reflection and using dynamic
is that by using reflection you can "cache" by type
part of the reflection, so speeding up later uses of type
methods, with dynamic
this doesn't happen.
Upvotes: 1
Reputation: 11601
If you know the type of your function like Func you can cast it directly as below
private static void InvokeFunctionDynamically<T>(T data)
{
//1. Define the delegate
Func<string, bool, T> genericFunction = (name, isEnabled) =>
{
if(isEnabled)
{
return data;
}
return default(T);
};
// 2. demonstrate that the delegate is retrieved at the run time as an object
object runtimeObject = genericFunction;
//3. Cast it directly to the delegate type
var result =((Func<string, bool, T>) runtimeObject)("hello", true);
Console.WriteLine($"Result {result}");
}
The results are below:
Upvotes: 0