Leo*_* Vo 25 .net c# anonymous-types
这是我的代码示例:
var output = new
{
NetSessionId = string.Empty
};
foreach (var property in output.GetType().GetProperties())
{
property.SetValue(output, "Test", null);
}
Run Code Online (Sandbox Code Playgroud)
它发生异常:"找不到属性集方法".我想知道如何创建一个具有可设置属性的匿名类型.
谢谢.
Mar*_*zek 34
匿名类型属性是只读的,无法设置.
匿名类型提供了一种将一组只读属性封装到单个对象中的便捷方法,而无需先显式定义类型.类型名称由编译器生成,在源代码级别不可用.每个属性的类型由编译器推断.
Ale*_*lex 23
如何设置匿名对象的属性值?
因为我今天被提醒的是,当将反射与关于如何实现某些事物的知识相结合时,没有什么是真正不可变的(在这种情况下支持匿名类型的只读属性的字段),我认为添加说明如何解释的答案是明智的可以通过将匿名对象映射到其支持字段来更改其属性值.
此方法依赖于编译器用于命名这些支持字段的特定约定:<xxxxx>i__Field在.NET和<xxxxx>Mono中,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;
}
}
Run Code Online (Sandbox Code Playgroud)
样品:
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);
}
Run Code Online (Sandbox Code Playgroud)
随着输出:
{ FirstField = Hello, AnotherField = 30 }
{ FirstField = Hello SO, AnotherField = 42 }
Run Code Online (Sandbox Code Playgroud)
这里可以找到更精细的版本
如果您遇到过需要可变类型的情况,而不是弄乱Anonymous类型,您可以使用ExpandoObject:
示例:
var people = new List<Person>
{
new Person { FirstName = "John", LastName = "Doe" },
new Person { FirstName = "Jane", LastName = "Doe" },
new Person { FirstName = "Bob", LastName = "Saget" },
new Person { FirstName = "William", LastName = "Drag" },
new Person { FirstName = "Richard", LastName = "Johnson" },
new Person { FirstName = "Robert", LastName = "Frost" }
};
// Method syntax.
var query = people.Select(p =>
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}); // or people.Select(p => GetExpandoObject(p))
// Query syntax.
var query2 = from p in people
select GetExpandoObject(p);
foreach (dynamic person in query2) // query2 or query
{
person.FirstName = "Changed";
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
// Used with the query syntax in this example, but may also be used
// with the method syntax just as easily.
private ExpandoObject GetExpandoObject(Person p)
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30309 次 |
| 最近记录: |