473,508 Members | 2,515 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

how do I dynamically create Func<t1, t2>?

I'm struggling here. Please help me complete this method:

Type ToFuncType(Type owningType, Type result)
{
return typeof(Func<typeof(owningType), typeof(result)>);
}

Or more generally, given a MethodInfo from GetGetMethod, what is the
fastest way to get a delegate to the method? I can hard-code the Func
type with Delegate.CreateDelegate and it does exactly what I want. I
just don't know how to dynamically get that from the MethodInfo.
Aug 14 '08 #1
6 5462
I figured it out. Alas, my plan failed miserably. I was trying to find
the fastest way to invoke 'get' methods. Anybody have a faster method
of getting data than those below? Here is my test code:

using System;
using System.Diagnostics;
using System.Reflection;
using NUnit.Framework;

namespace Asi.Tests.Xml
{
[TestFixture]
public class DynamicInvoker
{
public class Inker
{
public int Count;
public int ReadAndInc1 { get { return Count++; } }
public int ReadAndInc2 { get { return Count++; } }
public int ReadAndInc3 { get { return Count++; } }
public int ReadAndInc4 { get { return Count++; } }
public int ReadAndInc5 { get { return Count++; } }
}

static public TR RunFunc<T, TR>(MethodInfo meth, T target)
{
var func = (Func<T, TR>) Delegate.CreateDelegate(typeof (Func<T,
TR>), meth);
return func.Invoke(target);
}

public object InvokeFunc(MethodInfo meth, object obj)
{
if(!meth.ReflectedType.Equals(obj.GetType()))
throw new InvalidOperationException();
_makerSW.Start();
var genmeth = _maker.MakeGenericMethod(meth.ReflectedType,
meth.ReturnType);
_makerSW.Stop();
object ret = genmeth.Invoke(this, new[] { meth, obj });
return ret;
}

private MethodInfo _maker;
private readonly Stopwatch _makerSW = new Stopwatch();

[Test][Explicit("Too slow normally")]
public void DynamicInvokeSpeed()
{
var rand = new Random();
var sw1 = new Stopwatch();
var i1 = new Inker();
sw1.Reset(); sw1.Start();
object cnt = -1;
for (int i = 0; i < 100000; i++)
{
var prop = i1.GetType().GetProperty("ReadAndInc" + rand.Next(1,
5));
var meth = prop.GetGetMethod();
var del = (Func<Inker,
int>)Delegate.CreateDelegate(typeof(Func<Inker, int>), meth);
cnt = del.Invoke(i1);
}
Console.Out.WriteLine("hard-coded took " +
sw1.Elapsed.TotalSeconds);

var parms = new object[] { };
_maker = GetType().GetMethod("RunFunc", BindingFlags.Static |
BindingFlags.Public);
_makerSW.Reset();
sw1.Reset(); sw1.Start();
for (int i = 0; i < 100000; i++)
{
var prop = i1.GetType().GetProperty("ReadAndInc" + rand.Next(1,
5));
var meth = prop.GetGetMethod();
cnt = InvokeFunc(meth, i1);
}
Console.Out.WriteLine("Dynamic took " + sw1.Elapsed.TotalSeconds);
Console.Out.WriteLine("GenericMaker took " +
_makerSW.Elapsed.TotalSeconds);

sw1.Reset(); sw1.Start();
for (int i = 0; i < 100000; i++)
{
var prop = i1.GetType().GetProperty("ReadAndInc" + rand.Next(1,
5));
var meth = prop.GetGetMethod();
cnt = meth.Invoke(i1, parms);
}
Console.Out.WriteLine("Invoke took " + sw1.Elapsed.TotalSeconds);

sw1.Reset(); sw1.Start();
for (int i = 0; i < 100000; i++)
{
var prop = i1.GetType().GetProperty("ReadAndInc" + rand.Next(1,
5));
cnt = prop.GetValue(i1, null);
}
Console.Out.WriteLine("Reflect took " + sw1.Elapsed.TotalSeconds);
Console.Out.WriteLine("Cnt = " + cnt);
}
}
}
Aug 14 '08 #2
On Wed, 13 Aug 2008 19:30:01 -0700, not_a_commie <no********@gmail.com>
wrote:
I figured it out. Alas, my plan failed miserably. I was trying to find
the fastest way to invoke 'get' methods. Anybody have a faster method
of getting data than those below?
Odd that this should come up now. You might find some useful information
in one of Jon Skeet's recent blog posts:
http://msmvps.com/blogs/jon_skeet/ar...delegates.aspx

I didn't bother to look at your code very closely, it being somewhat out
of my interest and expertise. But at first glance, it does seem very
similar to what Jon's working on.

Pete
Aug 14 '08 #3
Thanks for the reply. Jon Skeet's article was the inspiration that
made me look into this approach. From my test of his method, there
would be no benefit unless you were repeatedly calling the same method
over and over. Typical (de)serialization doesn't do that. It only hits
each method once. There is probably some fancy DynamicMethod + IL
approach, but I don't know what it is. I did come up with another
approach (that is still not the fastest):

var prop = i1.GetType().GetProperty("ReadAndInc" + rand.Next(1, 5));
var meth = prop.GetGetMethod();
var dyn = DynamicMethod.GetMethodFromHandle(meth.MethodHandl e);
cnt = dyn.Invoke(i1, parms);
Aug 14 '08 #4
On Wed, 13 Aug 2008 21:04:54 -0700, not_a_commie <no********@gmail.com>
wrote:
Thanks for the reply. Jon Skeet's article was the inspiration that
made me look into this approach. From my test of his method, there
would be no benefit unless you were repeatedly calling the same method
over and over.
Yes, true. I obviously gave your specific problem too cursory a glance to
notice the difference. :)

That said, if you're just doing serialization on a single instance without
any opportunity for taking advantage of the delegate conversion, it's not
clear to me why performance is an issue at all. In any case, it may not
be possible to go much faster. Reflection is slow, so if you're trying to
write code that requires reflection, it's going to be slow. Only if you
can change the problem space or somehow cache the necessary data
structures, either approach basically removing reflection from the
equation, could you avoid the overhead of reflection.

Pete
Aug 14 '08 #5
not_a_commie <no********@gmail.comwrote:
Thanks for the reply. Jon Skeet's article was the inspiration that
made me look into this approach. From my test of his method, there
would be no benefit unless you were repeatedly calling the same method
over and over. Typical (de)serialization doesn't do that.
Ironically serialization is *exactly* the scenario that I was working
on. Yes, you only need to call the method once for a single object
being serialized, but IME you typically need to serialize/deserialize
many objects of the same type in the course of a program.

If you're only calling the method once, why do you want to create a
delegate from it in the first place?

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Aug 14 '08 #6
Thank you for the suggestions. I have some small geometry objects that
are serialized many times. I will modify my serialization attributes
on those to cache the appropriate delegates.
Aug 14 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
2384
by: Eric Lilja | last post by:
Hello, I was working on a program where I needed to take a vector storing objects of type std::string and convert each object to an int and store the ints in another vector. I decided that I should...
4
21402
by: PASQUALE | last post by:
Hi I have a question: do the both statements below give the same result? If yes then does somebody know something about preformance differencies using these joins? SELECT A.* FROM Table1 A...
18
2834
by: sam_cit | last post by:
Hi Everyone, int main() { printf("not included stdio.h"); } Yes, i haven't included stdio.h and my compiler would generate a warning and would assume that it would return a int, my question...
3
1843
by: subramanian100in | last post by:
Given two types T1 and T2, we can create pair<T1, T2p(value1, value2); where value1 and value2 are of types T1 and T2 respectively. Suppose we want to assign a new pair<value to p. We can do...
0
7231
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7336
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7405
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7504
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5643
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5059
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3198
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1568
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
773
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.