Skip to content

Instantly share code, notes, and snippets.

@cstrahan
Created May 12, 2010 01:44
Show Gist options
  • Save cstrahan/398092 to your computer and use it in GitHub Desktop.
Save cstrahan/398092 to your computer and use it in GitHub Desktop.
object stringUtil = new ExpandoObject();
// The CallSite that will handle setting the ToUpper member on stringUtil
var set_ToUpper_callSite = CallSite<Func<CallSite, object, Func<string, string>, object>>.Create(
Binder.SetMember(CSharpBinderFlags.None, "ToUpper", typeof(Program),
new[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
}));
Func<string, string> toUpper = str => str.ToUpper();
set_ToUpper_callSite.Target(set_ToUpper_callSite, stringUtil, toUpper);
// The CallSite that will handle the invocation of stringUtil.ToUpper(some_object_here)
var invoke_ToUpper_callsite = CallSite<Func<CallSite, object, string, object>>.Create(
Binder.InvokeMember(CSharpBinderFlags.None, "ToUpper", null, typeof(Program),
new[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
}));
var result = invoke_ToUpper_callsite.Target(invoke_ToUpper_callsite, stringUtil, "lower case text");
// The CallSite that will handle the invocation of Console.WriteLine(some_object_here)
var invoke_WriteLine_callsite = CallSite<Action<CallSite, Type, object>>.Create(
Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "WriteLine", null, typeof(Program),
new[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
invoke_WriteLine_callsite.Target(invoke_WriteLine_callsite, typeof(Console), result);
// Output: LOWER CASE TEXT
// We can't change this ...
// invoke_ToUpper_callsite = CallSite<Func<CallSite, string, object, object>>.Create(...)
// ... to this ...
// invoke_ToUpper_callsite = CallSite<Func<CallSite, object, object, object>>.Create(...)
// ... unless we change the second CSharpArgumentInfo:
var invoke_ToUpper_callsite = CallSite<Func<CallSite, object, object, object>>.Create(
Binder.InvokeMember(CSharpBinderFlags.None, "ToUpper", null, typeof(Program),
new[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
// Use CSharpArgumentInfoFlags.None,
// instead of CSharpArgumentInfoFlags.UseCompileTimeType
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
// When using CSharpArgumentInfoFlags.None, the DLR figures out the type that ToUpper expects (a string object),
// and converts the type as such. Otherwise, it would have thrown the following exception:
// RuntimeBinderException: Delegate 'System.Func<string,string>' has some invalid arguments
// I'm not sure *how* the DLR handles such conversions...
// ... does it try both explicit and implicit casts? Anything else?
dynamic stringUtil = new ExpandoObject();
Func<string, string> toUpper = str => str.ToUpper();
stringUtil.ToUpper = toUpper;
// Note: result is typed as dynamic!
var result = stringUtil.ToUpper("lower case text");
Console.WriteLine(result);
// Output: LOWER CASE TEXT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment