Challenge: Dynamically dynamic
Can you figure out a way to write the following code without using a try/catch?
class Program { static void Main(string[] args) { dynamic e = new ExpandoObject(); e.Name = "Ayende"; Console.WriteLine(HasProperty("Name", e)); Console.WriteLine(HasProperty("Id", e)); } private static bool HasProperty(string name, IDynamicMetaObjectProvider dyn) { try { var callSite = CallSite<Func<CallSite, object, object>>.Create( Binder.GetMember(CSharpBinderFlags.None, name, typeof (Program), new[] { CSharpArgumentInfo.Create( CSharpArgumentInfoFlags.None, null) })); callSite.Target(callSite, dyn); return true; } catch (RuntimeBinderException) { return false; } } }
The HasProperty method should accept any IDynamicMetaObjectProvider implementation, not just ExpandoObject.
Comments
<string,> )dyn).ContainsKey(name);
Doug,
Did you missed the part where I explicitly said that I wanted a solution that would work for things other than expando object?
This seems to work for me. Not really done much stuff with dynamic however - so it might be silly!
private static bool HasProperty(string name, IDynamicMetaObjectProvider dyn)
{
}
The only problem is that dynamic providers have to fill the GetDynamicMemberNames() themself. So it's possible that the original code will correctly return true while your code will return false.
The method will just return new string[0] by default, and it's ExpandoObject that just returns all known keys there.
I'm guessing this is a "fix" to the patch I just submitted ;-)
Matt,
Sort of, I can't figure out a good way to do that.
Is the try/catch method not a workable solution?
It is, but I don't like it
Sounds so simple to be silly, but waht about TryGetMember ?
I think the point was to avoid putting it in a Try/Catch. I'm guessing this is for RavenDB, try/catch constructs are expensive.
@Ayende,
By the way, I saw that RavenDB uses CodeDom to compile its indexes. My guess is that you chose this approach due to lack of good alternatives of code generation with 'dynamic' and expando objects.
What do you think about the fact that with each compilation CodeDom generates assemblies that remain loaded in the app domain?
Thanks,
T
Teleo,
That is okay by me, since indexes are rarely changing.
@Justin,
I had a couple of issues with your code, I have developed it further into this gist: http://gist.github.com/478382 . Based on reflection it can now also check existence of methods and property setters.
What about this? Dirty, but fully functional draft.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace DynamicCheckPropertyExistence
{
<func<callsite,>
<undefined";
<func dummyFalseResult = () => DUMMY_RESULT;
}
Constant DUMMY_RESULT has value "undefined"
public const string DUMMY_RESULT = "";
Spam or what? :) www . clipboard.cz/8af