In the asp.net helper, I pass the htmlAttributes variable of the form:

new { @class = "btn btn-default", title = "classic view" }; 

At the same time inside the helper, I sometimes need to add the css class active when a certain condition is met:

 new { @class = "btn btn-default active", title = "classic view" }; 

How to do it the easiest?

I myself tried to climb through reflection

 foreach (var i in htmlAttributes.GetType().GetProperties()) { Console.Write(i.GetValue(a)); } 

, but remembered that anonymous types are read-only, they are created without any setters .

Is it possible to create a copy with slightly different values?

    2 answers 2

    It all depends on what the consumer will do with this object. To pass to Razor helpers, the easiest way is to convert the object to RouteValueDictionary and then use another overload:

     var dict = new RouteValueDictionary(obj); dict["class"] += " active"; 

    You can also “trick” the consumer by passing him an object that implements ICustomTypeDescriptor — many consumers, including Razor, use ComponentModel instead of reflection to get the properties of the object.

    If the object is supposed to be transferred to interpreted languages ​​using DLR, then you can use ExpandoObject :

     var dict = (IDictionary<string, object>)new ExpandoObject(); foreach (var pair in new RouteValueDictionary(obj)) dict.Add(pair); dynamic foo = dict; foo.@class += " active"; 

    Well, if you need an exact match of the type - there's nothing to be done, you’ll have to use Andrei’s variant and hope that the compiler’s developers will not change the implementation features ...

      Simply create a new object through reflection, passing an array of values ​​to the constructor:

       static object CreateModified(object obj, string propName, object newValue) { var type = obj.GetType(); var props = type.GetProperties(); var values = props.Select(p => p.Name == propName ? newValue : p.GetValue(obj)).ToArray(); return Activator.CreateInstance(type, values); } 

      The solution is rather fragile; it relies on the fact that in the current implementation of the compiler, properties in an anonymous class are created in the same order as the parameters of its constructor.

      We use:

       var a = new { @class = "btn btn-default", title = "classic view" }; Console.WriteLine(a); var b = CreateModified(a, "class", a.@class + " active"); Console.WriteLine(b); 

      It seems to work, but I would not do that.

      • Well, at least you can still create it. I have already found a workaround, I was interested in the problem itself. - AK ♦
      • It is possible, there is a constructor that can be called, there are properties that can be read. - Andrew NOP