Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of DynamicObject or IDictionary<string, object> as context object #44

Closed
tomasceleda opened this issue Oct 23, 2018 · 3 comments
Assignees

Comments

@tomasceleda
Copy link

If I run

var values = new ServiceExample2() { { "X", 1 }, { "Y", 2 } };
int result = context.Execute<int>("X + Y", values);

where ServiceExample2 is inherits from Dictionary<string, object> it works as expected. When it implements IDictionary<string, object> or inherits DynamicObject and implements the properties dynamically, it throws NullReferenceException.

Is there some other way how to run on object with has not the properties known at compile time?

Thanks

@JonathanMagnan JonathanMagnan self-assigned this Oct 23, 2018
@JonathanMagnan
Copy link
Member

Hello @tomasceleda ,

There is a lot of way to do it.

For example: https://dotnetfiddle.net/zclC3l

// ExpandoObject
{
	dynamic dynamicObj = new ExpandoObject();
	dynamicObj.X = 1;
	dynamicObj.Y = 2;

	Console.WriteLine(Eval.Execute<int>("X + Y", dynamicObj));
}

// VariableFactory
{
	var context = new EvalContext();
	context.VariableFactory = arg => {
		if(arg.Name == "X")
		{
			arg.Value = 1;
			arg.IsHandled = true;
		}
		else if (arg.Name == "Y")
		{
			arg.Value = 2;
			arg.IsHandled = true;
		}
	};
	
	Console.WriteLine(context.Execute<int>("X + Y"));
}

We will look about your both scenario to see why it throw an error.

Best Regards,

Jonathan

@TehWardy
Copy link

TehWardy commented Nov 2, 2018

Interesting ... I hit this ...
https://stackoverflow.com/questions/53104874/querying-dynamic-data#53114267

Apart from the typo in my query code (referring to properties that don't exist I found that the problem was much the same.

I'm using Eval like this ...

public static class ObjectQueryExtensions
{
    static ObjectQueryExtensions()
    {
        EvalManager.DefaultContext.IncludeMemberFromAllParameters = true;
    }

    public static TResult Query<T, TResult>(this T source, Query query)
    {
        var code = query.ToCSharp();
        var result = Eval.Execute<object>(code, source);
        return JsonConvert.DeserializeObject<TResult>(JsonConvert.SerializeObject(result));
    }
}

... by doing the json bit at the end I can "not worry about selections having to create new t { }" instances during the querying process for the simple cost of a bit of cpu time (hense the reason that's there).

Query in this case is a custom thing I built to wrap around Eval, what it is is a Json based structure I can build out in my web based front end to define queries on objects.

In this case (as seen from the stackoverflow post I have a dynamic object that I built from getting data from multiple places (some items, some company data, ect) that I collected together in to my Eval context object.

Having done that I noticed using Eval in this manner must be doing something like this in the background when we use "EvalContext.IncludeMemberFromAllParameters = true" ...

IEnumerable<ExpandoObject> Items = source.Items;

Whereas if it did ...

IEnumerable<dynamic> Items = source.Items;

Then I believe this would work.
Lets also assume that for this whilst I actually have an ExpandoObject T is passed in as dynamic.

For the purpose of Eval here I think it might be "cleaner" in terms of user use case to always treat ExpandoObjects as dynamic although i have to admit I haven't really spent enough time to know for sure if that would cause unintended side effects.

@JonathanMagnan
Copy link
Member

Hello @tomasceleda ,

This issue will be closed since we answered it.

We will continue the @TehWardy request on the newly thread he created

Best Regards,

Jonathan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants