如何修改 匿名类型 中的属性值 ?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何修改 匿名类型 中的属性值 ?相关的知识,希望对你有一定的参考价值。
咨询区
Leo Vo
我有下面一段代码:
var output = new
NetSessionId = string.Empty
;
foreach (var property in output.GetType().GetProperties())
property.SetValue(output, "Test", null);
代码运行后,它会抛出如下异常:
Property set method not found
我想知道如何给这个 匿名类型
的属性赋值?
回答区
Alex
从 MSDN :https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/anonymous-types 的描述来看,理论上 匿名类型
是不可变的,一旦定义好之后,你是无法对它重新赋值。
但我想提醒的是,其实并没有所谓永恒的不可变,你要是真想变,肯定是有办法的,比如下面的 匿名类
。
var myAnonInstance = new
FirstField = "Hello",
AnotherField = 30,
;
当你用 ILSpy 反编译后代码如下:
internal sealed class <>f__AnonymousType0<<FirstField>j__TPar, <AnotherField>j__TPar>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <FirstField>j__TPar<FirstField> i__Field;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <AnotherField>j__TPar<AnotherField> i__Field;
public <FirstField>j__TPar FirstField
get
return < FirstField > i__Field;
public <AnotherField>j__TPar AnotherField
get
return < AnotherField > i__Field;
可以看到,底层的字段
其实是有默认规范的: <xxxxx>i__Field
, 这里的 xxxxx 就是属性名字,接下来就可以用 反射
来修改背后的字段
即可,参考代码如下:
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;
然后你可以这样使用。
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);
输出结果:
FirstField = Hello, AnotherField = 30
FirstField = Hello SO, AnotherField = 42
点评区
这个题目其实很有意思,虽然语言和框架设计者用了各种限制来阻止我们做一些事情,其实都有化解的方法,所以并没有永恒的不可变,最彻底的还可以通过修改内存地址变更,不是嘛~
以上是关于如何修改 匿名类型 中的属性值 ?的主要内容,如果未能解决你的问题,请参考以下文章