public void TestSetDynamicChainedOne() { var tSetValue = "1"; dynamic tExpando = new ExpandoObject(); Impromptu.InvokeSetChain(tExpando, "Test", tSetValue); Assert.AreEqual(tSetValue, tExpando.Test); }
public void TestSetDynamicChainedWithInexes() { var tSetValue = "1"; dynamic tExpando = Build.NewObject( Test: Build.NewObject( Test2: Build.NewList( Build.NewObject(Test3: Build.NewObject()) ) ) ); var tOut = Impromptu.InvokeSetChain(tExpando, "Test.Test2[0].Test3['Test4']", tSetValue); Assert.AreEqual(tSetValue, tExpando.Test.Test2[0].Test3["Test4"]); Assert.AreEqual(tSetValue, tOut); }
public void TestSetDynamicAllDict() { var tSetValue = "1"; dynamic tExpando = new ExpandoObject(); tExpando.Test = new ExpandoObject(); tExpando.Test.Test2 = new ExpandoObject(); Impromptu.InvokeSetAll(tExpando, new Dictionary <string, object> { { "Test.Test2.Test3", tSetValue }, { "One", 1 }, { "Two", 2 } }); Impromptu.InvokeSetChain(tExpando, "Test.Test2.Test3", tSetValue); Assert.AreEqual(tSetValue, tExpando.Test.Test2.Test3); Assert.AreEqual(1, tExpando.One); Assert.AreEqual(2, tExpando.Two); }
/// <summary> /// Provides the implementation for operations that invoke an object. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations such as invoking an object or a delegate. /// </summary> /// <param name="binder">Provides information about the invoke operation.</param> /// <param name="args">The arguments that are passed to the object during the invoke operation. For example, for the sampleObject(100) operation, where sampleObject is derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, <paramref name="args"/>[0] is equal to 100.</param> /// <param name="result">The result of the object invocation.</param> /// <returns> /// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown. /// </returns> public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) { IEnumerable <KeyValuePair <string, object> > tDict = null; object target = null; result = null; //Setup Properties as dictionary if (binder.CallInfo.ArgumentNames.Any()) { if (binder.CallInfo.ArgumentNames.Count + 1 == binder.CallInfo.ArgumentCount) { target = args.First(); tDict = binder.CallInfo.ArgumentNames .Zip(args.Skip(1), (key, value) => new { key, value }) .ToDictionary(k => k.key, v => v.value); } else { throw new RuntimeBinderException("InvokeSetAll requires first parameter to be target unamed, and all other parameters to be named."); } } else if (args.Length == 2) { target = args[0]; if (args[1] is IEnumerable <KeyValuePair <string, object> > ) { tDict = (IEnumerable <KeyValuePair <string, object> >)args[1]; } else if (args[1] is IEnumerable && args[1].GetType().IsGenericType ) { var tEnumerableArg = (IEnumerable)args[1]; var tInterface = tEnumerableArg.GetType().GetInterface("IEnumerable`1", false); if (tInterface != null) { var tParamTypes = tInterface.GetGenericArguments(); if (tParamTypes.Length == 1 && tParamTypes[0].GetGenericTypeDefinition() == typeof(Tuple <,>)) { tDict = tEnumerableArg.Cast <dynamic>().ToDictionary(k => (string)k.Item1, v => (object)v.Item2); } } } else if (Util.IsAnonymousType(args[1])) { var keyDict = new Dictionary <string, object>(); foreach (var tProp in args[1].GetType().GetProperties()) { keyDict[tProp.Name] = Impromptu.InvokeGet(args[1], tProp.Name); } tDict = keyDict; } } //Invoke all properties if (target != null && tDict != null) { foreach (var tPair in tDict) { Impromptu.InvokeSetChain(target, tPair.Key, tPair.Value); } result = target; return(true); } return(false); }