private DynamicMetaObject GetMetaSelf(DynamicMetaObject /*!*/ self) { DynamicMetaObject func; IDynamicMetaObjectProvider ido = Value.im_self as IDynamicMetaObjectProvider; if (ido != null) { func = ido.GetMetaObject(GetSelfExpression(self)); } else if (Value.im_self == null) { func = new DynamicMetaObject( GetSelfExpression(self), BindingRestrictions.Empty); } else { func = new DynamicMetaObject( GetSelfExpression(self), BindingRestrictions.Empty, Value.im_self ); } return(func); }
private static IList <KeyValuePair <string, object> > QueryDynamicObject(object obj) { IDynamicMetaObjectProvider ido = obj as IDynamicMetaObjectProvider; if (ido != null) { DynamicMetaObject mo = ido.GetMetaObject(parameter); List <string> names = new List <string>(mo.GetDynamicMemberNames()); names.Sort(); var result = new List <KeyValuePair <string, object> >(); foreach (string name in names) { object value; if ((value = TryGetMemberValue(obj, name, true)) != null) { result.Add(new KeyValuePair <string, object>(name, value)); } } return(result); } #if ENABLECOMBINDER else if (obj != null && ComObjectType.IsAssignableFrom(obj.GetType())) { IList <string> names = ComInterop.ComBinder.GetDynamicDataMemberNames(obj); return(ComInterop.ComBinder.GetDynamicDataMembers(obj, names.OrderBy(n => n))); } #endif return(Array.Empty <KeyValuePair <string, object> >()); }
private static void GetDynamicMemberBindings(IDynamicMetaObjectProvider @dynamic, Type conversionType, ParameterExpression parExp, List <MemberBinding> bindings, ConvertMapper mapper) { var method = typeof(DynamicManager).GetMethod("GetMember", BindingFlags.Instance | BindingFlags.Public); var metaObject = @dynamic.GetMetaObject(Expression.Constant(@dynamic)); var metaObjExp = Expression.TypeAs(parExp, typeof(IDynamicMetaObjectProvider)); foreach (var name in metaObject.GetDynamicMemberNames()) { try { var descProperty = conversionType.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); if (descProperty == null || !descProperty.CanWrite) { continue; } var mgrExp = Expression.New(typeof(DynamicManager)); var exp = (Expression)Expression.Call(mgrExp, method, metaObjExp, Expression.Constant(name)); exp = Expression.Call(null, MthToType, exp, Expression.Constant(descProperty.PropertyType), Expression.Constant(null)); exp = (Expression)Expression.Convert(exp, descProperty.PropertyType); bindings.Add(Expression.Bind(descProperty, exp)); } catch { continue; } } }
private static void Iterate( ObjectEnumeratorBindingContext context, IDynamicMetaObjectProvider target, Action <TextWriter, object> template, Action <TextWriter, object> ifEmpty) { if (HandlebarsUtils.IsTruthy(target)) { context.Index = 0; var meta = target.GetMetaObject(Expression.Constant(target)); foreach (var enumerableValue in new ExtendedEnumerable <string>(meta.GetDynamicMemberNames())) { var name = enumerableValue.Value; context.Key = name; var value = GetProperty(target, name); context.First = enumerableValue.IsFirst; context.Last = enumerableValue.IsLast; context.Index = enumerableValue.Index; template(context.TextWriter, value); } if (context.Index == 0) { ifEmpty(context.TextWriter, context.Value); } } else { ifEmpty(context.TextWriter, context.Value); } }
private static IList <KeyValuePair <string, object> > QueryDynamicObject(object obj) { IDynamicMetaObjectProvider ido = obj as IDynamicMetaObjectProvider; if (ido != null) { DynamicMetaObject mo = ido.GetMetaObject(parameter); List <string> names = new List <string>(mo.GetDynamicMemberNames()); names.Sort(); if (names != null) { var result = new List <KeyValuePair <string, object> >(); foreach (string name in names) { object value; if ((value = TryGetMemberValue(obj, name, true)) != null) { result.Add(new KeyValuePair <string, object>(name, value)); } } return(result); } } return(Array.Empty <KeyValuePair <string, object> >()); }
/// <summary> /// Creates the action for a dynamic object. /// </summary> /// <param name="provider">The dynamic object.</param> protected virtual Delegate CreateActionForDynamic(IDynamicMetaObjectProvider provider) { // http://stackoverflow.com/a/14011692/68499 var type = provider.GetType(); var parameterExpression = Expression.Parameter(typeof(object), "record"); var metaObject = provider.GetMetaObject(parameterExpression); var propertyNames = metaObject.GetDynamicMemberNames(); var delegates = new List <Delegate>(); foreach (var propertyName in propertyNames) { var getMemberBinder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, propertyName, type, new[] { CSharpArgumentInfo.Create(0, null) }); var getMemberMetaObject = metaObject.BindGetMember(getMemberBinder); var fieldExpression = getMemberMetaObject.Expression; fieldExpression = Expression.Call(Expression.Constant(this), nameof(WriteField), new[] { typeof(object) }, fieldExpression); fieldExpression = Expression.Block(fieldExpression, Expression.Label(CallSiteBinder.UpdateLabel)); var lambda = Expression.Lambda(fieldExpression, parameterExpression); delegates.Add(lambda.Compile()); } var action = CombineDelegates(delegates); context.TypeActions[type] = action; return(action); }
/// <summary> /// Creates a meta-object for the specified object. /// </summary> /// <param name="value">The object to get a meta-object for.</param> /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param> /// <returns> /// If the given object implements <see cref="IDynamicMetaObjectProvider"/> and is not a remote object from outside the current AppDomain, /// returns the object's specific meta-object returned by <see cref="IDynamicMetaObjectProvider.GetMetaObject"/>. Otherwise a plain new meta-object /// with no restrictions is created and returned. /// </returns> public static DynamicMetaObject Create(object value, Expression expression) { ContractUtils.RequiresNotNull(expression, nameof(expression)); IDynamicMetaObjectProvider ido = value as IDynamicMetaObjectProvider; if (ido != null) { var idoMetaObject = ido.GetMetaObject(expression); if (idoMetaObject == null || !idoMetaObject.HasValue || idoMetaObject.Value == null || (object)idoMetaObject.Expression != (object)expression) { throw System.Linq.Expressions.Error.InvalidMetaObjectCreated(ido.GetType()); } return(idoMetaObject); } else { return(new DynamicMetaObject(expression, BindingRestrictions.Empty, value)); } }
private static void GetDynamicMemberAssignments(IDynamicMetaObjectProvider @dynamic, Type targetType, ParameterExpression sourceParExp, ParameterExpression targetParExp, List <BinaryExpression> assignments, ConvertMapper mapper) { var method = typeof(DynamicManager).GetMethod(nameof(DynamicManager.GetMember), BindingFlags.Instance | BindingFlags.Public); var metaObject = @dynamic.GetMetaObject(Expression.Constant(@dynamic)); var metaObjExp = Expression.TypeAs(sourceParExp, typeof(IDynamicMetaObjectProvider)); foreach (var name in metaObject.GetDynamicMemberNames()) { try { var descProperty = targetType.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); if (descProperty == null || !descProperty.CanWrite) { continue; } var mgrExp = Expression.New(typeof(DynamicManager)); var exp = (Expression)Expression.Call(mgrExp, method, metaObjExp, Expression.Constant(name)); exp = Expression.Call(null, MethodCache.ToType, exp, Expression.Constant(descProperty.PropertyType), Expression.Constant(null), Expression.Constant(null, typeof(ConvertMapper))); exp = (Expression)Expression.Convert(exp, descProperty.PropertyType); var descExp = Expression.MakeMemberAccess(targetParExp, descProperty); assignments.Add(Expression.Assign(descExp, exp)); } catch { continue; } } }
public override object GetValue(object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, object[] index, System.Globalization.CultureInfo culture) { Func <object> del; if (cache.TryGetValue(obj, out del)) { return(del.Invoke()); } IDynamicMetaObjectProvider provider = obj as IDynamicMetaObjectProvider; DynamicMetaObject mobj; if (provider != null) { mobj = provider.GetMetaObject(Expression.Constant(obj)); } else { mobj = new DynamicMetaObject(Expression.Constant(obj), BindingRestrictions.Empty, obj); } DynamicMetaObject ret = mobj.BindGetMember(dbinder); BlockExpression final = Expression.Block( Expression.Label(CallSiteBinder.UpdateLabel), ret.Expression ); Expression <Func <object> > lambda = Expression.Lambda <Func <object> >(final); del = lambda.Compile(); cache[obj] = del; return(del.Invoke()); }
public static object GetProperty(this object o, string member) { if (o == null) { throw new ArgumentNullException("o"); } if (member == null) { throw new ArgumentNullException("member"); } Type scope = o.GetType(); IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider; if (provider != null) { ParameterExpression param = Expression.Parameter(typeof(object)); DynamicMetaObject mobj = provider.GetMetaObject(param); GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) }); DynamicMetaObject ret = mobj.BindGetMember(binder); BlockExpression final = Expression.Block( Expression.Label(CallSiteBinder.UpdateLabel), ret.Expression ); LambdaExpression lambda = Expression.Lambda(final, param); Delegate del = lambda.Compile(); return(del.DynamicInvoke(o)); } else { return(o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null)); } }
private static void Iterate( ObjectEnumeratorBindingContext context, IDynamicMetaObjectProvider target, Action <TextWriter, object> template, Action <TextWriter, object> ifEmpty) { if (HandlebarsUtils.IsTruthy(target)) { context.Index = 0; var meta = target.GetMetaObject(System.Linq.Expressions.Expression.Constant(target)); foreach (var name in meta.GetDynamicMemberNames()) { context.Key = name; var value = GetProperty(target, name); context.First = (context.Index == 0); template(context.TextWriter, value); context.Index++; } if (context.Index == 0) { ifEmpty(context.TextWriter, context.Value); } } else { ifEmpty(context.TextWriter, context.Value); } }
/// <summary> /// Creates a meta-object for the specified object. /// </summary> /// <param name="value">The object to get a meta-object for.</param> /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param> /// <returns> /// If the given object implements <see cref="IDynamicMetaObjectProvider"/> and is not a remote object from outside the current AppDomain, /// returns the object's specific meta-object returned by <see cref="IDynamicMetaObjectProvider.GetMetaObject"/>. Otherwise a plain new meta-object /// with no restrictions is created and returned. /// </returns> public static DynamicMetaObject Create(object value, Expression expression) { ContractUtils.RequiresNotNull(expression, "expression"); IDynamicMetaObjectProvider ido = value as IDynamicMetaObjectProvider; #if !SILVERLIGHT if (ido != null && !RemotingServices.IsObjectOutOfAppDomain(value)) { #else if (ido != null) { #endif var idoMetaObject = ido.GetMetaObject(expression); if (idoMetaObject == null || !idoMetaObject.HasValue || idoMetaObject.Value == null || (object)idoMetaObject.Expression != (object)expression) { throw Error.InvalidMetaObjectCreated(ido.GetType()); } return(idoMetaObject); } else { return(new DynamicMetaObject(expression, BindingRestrictions.Empty, value)); } } }
/// <summary> /// Writes the header record for the given dynamic object. /// </summary> /// <param name="record">The dynamic record to write.</param> public virtual void WriteDynamicHeader(IDynamicMetaObjectProvider record) { if (record == null) { throw new ArgumentNullException(nameof(record)); } if (!context.WriterConfiguration.HasHeaderRecord) { throw new CsvWriterException(context, "Configuration.HasHeaderRecord is false. This will need to be enabled to write the header."); } if (context.HasHeaderBeenWritten) { throw new CsvWriterException(context, "The header record has already been written. You can't write it more than once."); } if (context.HasHeaderBeenWritten) { throw new CsvWriterException(context, "Records have already been written. You can't write the header after writing records has started."); } var metaObject = record.GetMetaObject(Expression.Constant(record)); var names = metaObject.GetDynamicMemberNames(); foreach (var name in names) { WriteField(name); } context.HasHeaderBeenWritten = true; }
protected virtual DynamicMetaObject CreatePrototypeMetaObject() { UnaryExpression castExpression = Expression.Convert(Expression, Value.GetType()); MemberExpression memberExpression = Expression.Property(castExpression, "Prototype"); DynamicMetaObject prototypeMetaObject = _prototype.GetMetaObject(memberExpression); return(prototypeMetaObject); }
private static IEnumerable <string> GetDynamicMemberNames(dynamic obj) { IDynamicMetaObjectProvider provider = obj as IDynamicMetaObjectProvider; Expression expression = Expression.Parameter(typeof(object), "$arg0"); DynamicMetaObject dynamicMetaObject = provider.GetMetaObject(expression); IEnumerable <string> result = dynamicMetaObject.GetDynamicMemberNames(); return(result.ToList()); }
public static PropertyInfo GetPropertyInfoInternal(this object o, string member) { try { if (o == null) { throw new ArgumentNullException("o"); } if (member == null) { throw new ArgumentNullException("member"); } Type scope = o.GetType(); IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider; if (provider != null) { var odictionary = (IDictionary <string, object>)o; if (!odictionary.Any(x => x.Key.Equals(member, StringComparison.OrdinalIgnoreCase))) { return(null); } var odynamic = odictionary.FirstOrDefault(x => x.Key.Equals(member, StringComparison.OrdinalIgnoreCase)); member = odynamic.Key; //if (!odynamic.ContainsKey(member)) return null; //if (odynamic.Any(x => x.Key.ToLower() == member.ToLower())) return null; ParameterExpression param = Expression.Parameter(typeof(object)); DynamicMetaObject mobj = provider.GetMetaObject(param); GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new[] { CSharpArgumentInfo.Create(0, null) }); DynamicMetaObject ret = mobj.BindGetMember(binder); BlockExpression final = Expression.Block( Expression.Label(CallSiteBinder.UpdateLabel), ret.Expression ); LambdaExpression lambda = Expression.Lambda(final, param); Delegate del = lambda.Compile(); return(null); //return del.DynamicInvoke(o); } else { var oProperty = o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if (oProperty != null) { //return oProperty.GetValue(o, null); return(oProperty); } return(null); } } catch (Exception) { return(null); } }
public static IEnumerable <string> GetDynamicMemberNames( this IDynamicMetaObjectProvider dynamicProvider ) { DynamicMetaObject metaObject = dynamicProvider.GetMetaObject( Expression.Constant(dynamicProvider) ); return(metaObject.GetDynamicMemberNames()); }
public MyMetaObject(Expression parameter, ExtendedExpandoObject value) : base(parameter, BindingRestrictions.Empty, value) { var valueParameter = Expression.Property( Expression.Convert(parameter, typeof(ExtendedExpandoObject)), "Value" ); IDynamicMetaObjectProvider provider = value.Value; ValueMetaObject = provider.GetMetaObject(valueParameter); }
public MyMetaObject(Expression parameter, ExtendedExpandoObject value, DynamicMetaObject metaObject) : base(metaObject) { var valueParameter = Expression.Property( Expression.Convert(parameter, typeof(ExtendedExpandoObject)), "Value" ); IDynamicMetaObjectProvider provider = value.Value; ValueMetaObject = provider.GetMetaObject(valueParameter); }
public PropertyDescriptorCollection GetProperties() { var meta = _dynamic.GetMetaObject(Expression.Constant(_dynamic)); var memberNames = meta.GetDynamicMemberNames(); var props = new PropertyDescriptorCollection(new PropertyDescriptor[] { }); foreach (var memberName in memberNames) { if (!properties.ContainsKey(memberName)) { var newProperty = new DynamicPropertyDescriptor(_dynamic, memberName); properties.Add(memberName, newProperty); } props.Add(properties[memberName]); } return(props); }
public ForwardingMetaObject(Expression expression, BindingRestrictions restrictions, object forwarder, IDynamicMetaObjectProvider forwardee, Func <Expression, Expression> forwardeeGetter) : base(expression, restrictions, forwarder) { // We'll use forwardee's meta-object to bind dynamic operations. _metaForwardee = forwardee.GetMetaObject( forwardeeGetter( Expression.Convert(expression, forwarder.GetType()) // [1] ) ); }
static void SerializeDynamicObject(IDynamicMetaObjectProvider dyn, TextWriter stream, Options opts, int depth) { var quoteColon = "\":"; if (opts.ShouldPrettyPrint) { quoteColon = "\": "; } stream.Write('{'); depth++; var dynType = dyn.GetType(); var metaObj = dyn.GetMetaObject(CachedParameterExp); var first = true; foreach (var memberName in metaObj.GetDynamicMemberNames()) { var getter = GetGetMember(dynType, memberName); var val = getter(dyn); if (val == null && opts.ShouldExcludeNulls) { continue; } if (!first) { stream.Write(','); } first = false; if (opts.ShouldPrettyPrint) { LineBreakAndIndent(stream, depth); } stream.Write('"'); stream.Write(memberName.JsonEscape(jsonp: opts.IsJSONP)); stream.Write(quoteColon); Serialize(stream, val, opts, depth + 1); } depth--; if (opts.ShouldPrettyPrint) { LineBreakAndIndent(stream, depth); } stream.Write('}'); }
/// <summary> /// Creates an instance of <see cref="DynamicMetaObject"/> for a runtime value and the expression that represents it during the binding process. /// </summary> /// <param name="argValue">The runtime value to be represented by the <see cref="DynamicMetaObject"/>.</param> /// <param name="parameterExpression">An expression to represent this <see cref="DynamicMetaObject"/> during the binding process.</param> /// <returns>The new instance of <see cref="DynamicMetaObject"/>.</returns> public static DynamicMetaObject ObjectToMetaObject(object argValue, Expression parameterExpression) { IDynamicMetaObjectProvider ido = argValue as IDynamicMetaObjectProvider; if (ido != null) { return(ido.GetMetaObject(parameterExpression)); } else { return(new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty, argValue)); } }
public Dictionary <string, object> GetDynamicMemberNameAndValues(IDynamicMetaObjectProvider dynamicObject) { dynamicObject.IsNullThrow(nameof(dynamicObject)); var dictionary = new Dictionary <string, object>(); var names = dynamicObject.GetMetaObject(Expression.Constant(dynamicObject)).GetDynamicMemberNames(); foreach (var name in names) { if (TryGetMember(dynamicObject, name, out var value)) { dictionary.Add(name, value); } } return(dictionary); }
public ForwardingMetaObject( Expression expression, BindingRestrictions restrictions, object forwarder, IDynamicMetaObjectProvider forwardee, Func<Expression, Expression> forwardeeGetter ) : base(expression, restrictions, forwarder) { // We'll use forwardee's meta-object to bind dynamic operations. metaForwardee = forwardee.GetMetaObject( forwardeeGetter( Expression.Convert(expression, forwarder.GetType()) // [1] ) ); }
public static DynamicMetaObject Create(object value, System.Linq.Expressions.Expression expression) { ContractUtils.RequiresNotNull(expression, "expression"); IDynamicMetaObjectProvider provider = value as IDynamicMetaObjectProvider; if ((provider == null) || RemotingServices.IsObjectOutOfAppDomain(value)) { return(new DynamicMetaObject(expression, BindingRestrictions.Empty, value)); } DynamicMetaObject metaObject = provider.GetMetaObject(expression); if (((metaObject == null) || !metaObject.HasValue) || ((metaObject.Value == null) || (metaObject.Expression != expression))) { throw Error.InvalidMetaObjectCreated(provider.GetType()); } return(metaObject); }
private static object GetPropertyValueByProvider(object o, string member, IDynamicMetaObjectProvider provider, Type scope) { var param = Expression.Parameter(typeof(object)); var mobj = provider.GetMetaObject(param); var binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new[] { CSharpArgumentInfo.Create(0, null) }); var ret = mobj.BindGetMember(binder); var final = Expression.Block( Expression.Label(CallSiteBinder.UpdateLabel), ret.Expression ); var lambda = Expression.Lambda(final, param); var del = lambda.Compile(); return(del.DynamicInvoke(o)); }
/// <summary> /// __dir__(self) -> Returns the list of members defined on a foreign IDynamicMetaObjectProvider. /// </summary> public static List DynamicDir(CodeContext /*!*/ context, IDynamicMetaObjectProvider self) { List res = new List(self.GetMetaObject(Expression.Parameter(typeof(object))).GetDynamicMemberNames()); // add in the non-dynamic members from the dynamic objects base class. Type t = self.GetType(); while (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t)) { t = t.GetBaseType(); } res.extend(DynamicHelpers.GetPythonTypeFromType(t).GetMemberNames(context)); res.sort(context); return(res); }
private string getInsertString(string tableName, IDynamicMetaObjectProvider value) { StringBuilder sqlPs = new StringBuilder(""); StringBuilder sqlVs = new StringBuilder(""); var properties = value.GetMetaObject(Expression.Constant(value)).GetDynamicMemberNames(); int len = properties.Count(); int i = 0; foreach (var name in properties) { var split = i++ < len - 1 ? "," : ""; sqlPs.AppendFormat("{0}{1}", name, split); sqlVs.AppendFormat("@{0}{1}", name, split); } return(string.Format("INSERT INTO {0}({1}) VALUES({2})", tableName, sqlPs, sqlVs)); }
private DynamicMetaObject /*!*/ GetMetaFunction(DynamicMetaObject /*!*/ self) { DynamicMetaObject func; IDynamicMetaObjectProvider ido = Value.im_func as IDynamicMetaObjectProvider; if (ido != null) { func = ido.GetMetaObject(GetFunctionExpression(self)); } else { func = new DynamicMetaObject( GetFunctionExpression(self), BindingRestrictions.Empty ); } return(func); }
private static PropertyReader[] GetDynamicProperties(IDynamicMetaObjectProvider provider) { var metaObject = provider.GetMetaObject(Expression.Constant(provider)); // may return property names as well as method names, etc. var memberNames = metaObject.GetDynamicMemberNames(); var result = new List <PropertyReader>(); foreach (var name in memberNames) { try { var argumentInfo = new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }; var binder = Binder.GetMember( CSharpBinderFlags.None, name, provider.GetType(), argumentInfo); var site = CallSite <Func <CallSite, object, object> > .Create(binder); // will throw if no valid property getter var value = site.Target(site, provider); result.Add(new PropertyReader { Name = name, DeclaringType = provider.GetType(), Read = o => value }); } catch (RuntimeBinderException) { } } return(result.ToArray()); }
private static PropertyReader[] GetDynamicProperties(IDynamicMetaObjectProvider provider) { var metaObject = provider.GetMetaObject(Expression.Constant(provider)); var memberNames = metaObject.GetDynamicMemberNames(); // may return property names as well as method names, etc. var result = new List<PropertyReader>(); foreach (var name in memberNames) { try { var argumentInfo = new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}; var binder = Binder.GetMember(CSharpBinderFlags.None, name, provider.GetType(), argumentInfo); var site = CallSite<Func<CallSite, object, object>>.Create(binder); var value = site.Target(site, provider); // will throw if no valid property getter result.Add(new PropertyReader { Name = name, DeclaringType = provider.GetType(), Read = o => value }); } catch (RuntimeBinderException) { } } return result.ToArray(); }
private static void Iterate( ObjectEnumeratorBindingContext context, IDynamicMetaObjectProvider target, Action<TextWriter, object> template, Action<TextWriter, object> ifEmpty) { if (HandlebarsUtils.IsTruthy(target)) { context.Index = 0; var meta = target.GetMetaObject(Expression.Constant(target)); foreach (var name in meta.GetDynamicMemberNames()) { context.Key = name; var value = GetProperty(target, name); context.First = (context.Index == 0); template(context.TextWriter, value); context.Index++; } if (context.Index == 0) { ifEmpty(context.TextWriter, context.Value); } } else { ifEmpty(context.TextWriter, context.Value); } }