this is my code for example:
var output = new { NetSessionId = string.Empty }; foreach (var property in output.GetType().GetProperties()) { property.SetValue(output, "Test", null); }
It occurs an exception: "Property set method not found". I want to know how to create an anonymous type with properties which can be set.
Thanks.
You create anonymous types by using the new operator together with an object initializer. For more information about object initializers, see Object and Collection Initializers. The following example shows an anonymous type that is initialized with two properties named Amount and Message .
In LINQ, select clause generates anonymous type so that in a query you can include properties that are not defined in the class.
In C#, an anonymous type is a type (class) without any name that can contain public read-only properties only. It cannot contain other members, such as fields, methods, events, etc. You create an anonymous type using the new operator with an object initializer syntax.
Anonymous type properties are read only and they cannot be set.
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
Anonymous Types (C# Programming Guide)
How to set value for property of an anonymous object?
Because I was reminded today that nothing is truly immutable when using reflection in combination with knowledge on how certain things are implemented (backing fields for the read-only properties of anonymous types in this case), I thought it wise to add an answer illustrating how the property values of an anonymous object can be changed, by mapping them to their backing fields.
This method relies on a specific convention used by the compiler for naming these backing fields: <xxxxx>i__Field
in .NET and <xxxxx>
on Mono, with the xxxxx
representing the property name. If this convention were to change, the code below will fail (note: it will also fail if you try to feed it something that is not an anonymous type).
public static class AnonymousObjectMutator { private const BindingFlags FieldFlags = BindingFlags.NonPublic | BindingFlags.Instance; private static readonly string[] BackingFieldFormats = { "<{0}>i__Field", "<{0}>" }; public static T Set<T, TProperty>( this T instance, Expression<Func<T, TProperty>> propExpression, TProperty newValue) where T : class { var pi = (propExpression.Body as MemberExpression).Member; var backingFieldNames = BackingFieldFormats.Select(x => string.Format(x, pi.Name)).ToList(); var fi = typeof(T) .GetFields(FieldFlags) .FirstOrDefault(f => backingFieldNames.Contains(f.Name)); if (fi == null) throw new NotSupportedException(string.Format("Cannot find backing field for {0}", pi.Name)); fi.SetValue(instance, newValue); return instance; } }
Sample:
public static void Main(params string[] args) { var myAnonInstance = new { FirstField = "Hello", AnotherField = 30, }; Console.WriteLine(myAnonInstance); myAnonInstance .Set(x => x.FirstField, "Hello SO") .Set(x => x.AnotherField, 42); Console.WriteLine(myAnonInstance); }
With output:
{ FirstField = Hello, AnotherField = 30 } { FirstField = Hello SO, AnotherField = 42 }
A slightly more elaborate version can be found here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With