gpt4 book ai didi

c# - 保证列表中属性的顺序与它们在代码文件中出现的顺序相匹配

转载 作者:行者123 更新时间:2023-11-30 20:08:32 25 4
gpt4 key购买 nike

我有一个接口(interface),它定义了一个返回 IList<PropertyInfo> 的方法。 :

public interface IWriteable
{
IList<PropertyInfo> WriteableProperties();
}

.
.
它以下列方式在各种(不同的)类中实现:

public abstract class Foo
{
private IList<PropertyInfo> _props;

protected Foo()
{
this._props = new List<PropertyInfo>();

foreach (PropertyInfo p in this.GetType().GetProperties())
{
if (Attribute.IsDefined(p, typeof(WriteableAttribute)))
this._props.Add(p);
}
}

#region IWriteable Members

public IList<PropertyInfo> WriteableProperties()
{
return this._props;
}

#endregion
}

public class Bar : Foo
{
public string A
{
get { return "A"; }
}

[Writeable()]
public string B
{
get { return "B"; }
}

[Writeable()]
public string C
{
get { return "C"; }
}

// Snip
}

请注意标记几个属性的属性,因为这些是将添加到列表中的属性。这IList然后将在某些文件写入操作期间在其他地方使用。

对我来说重要的是,它们在列表中的排列顺序与它们在代码文件中出现的顺序相同。

然而,MSDN状态:

The GetProperties method does not return properties in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which properties are returned, because that order varies.

那么,确保每个 PropertyInfo 都按照我希望的顺序添加的最佳方法是什么?

(我也在使用 .NET2.0,所以我不能使用任何 Linq 优点,如果有任何有用的东西,虽然它会很有趣。)

最佳答案

将有关排序的信息添加到属性中,然后您可以使用它来确保排序,例如:

[Writeable(Order = 1)]

所以对于以下属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class WriteableAttribute : Attribute
{
public int Order { get; set; }
}

您可以获得属性的有序选择,如下所示:

private readonly List<PropertyInfo> _props;

protected Foo()
{
_props = new List<PropertyInfo>();

var props = new Dictionary<int, PropertyInfo>();

foreach (PropertyInfo p in GetType().GetProperties())
{
if (Attribute.IsDefined(p, typeof(WriteableAttribute)))
{
var attr = (WriteableAttribute)p
.GetCustomAttributes(typeof(WriteableAttribute))[0];

props.Add(attr.Order, p);
}
}

_props.AddRange(props.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value));
}

注意 对于生产代码,我建议缓存属性信息(例如按类型),因为如果针对每个实例执行这将相对较慢。

更新 - 缓存

通过一些示例缓存属性查找和排序:

public static class PropertyReflector
{
private static readonly object SyncObj = new object();

private static readonly Dictionary<Type, List<PropertyInfo>> PropLookup =
new Dictionary<Type, List<PropertyInfo>>();

public static IList<PropertyInfo> GetWritableProperties(Type type)
{
lock (SyncObj)
{
List<PropertyInfo> props;

if (!PropLookup.TryGetValue(type, out props))
{
var propsOrder = new Dictionary<int, PropertyInfo>();

foreach (PropertyInfo p in type.GetProperties())
{
if (Attribute.IsDefined(p, typeof(WriteableAttribute)))
{
var attr = (WriteableAttribute)p.GetCustomAttributes(
typeof(WriteableAttribute), inherit: true)[0];

propsOrder.Add(attr.Order, p);
}
}

props = new List<PropertyInfo>(propsOrder
.OrderBy(kvp => kvp.Key)
.Select(kvp => kvp.Value));

PropLookup.Add(type, props);
}

return props;
}
}
}

更新 - 无 Linq

您可以将 Linq 部分替换为以下代码以对属性进行排序并将它们添加到缓存中:

List<int> order = new List<int>(propsOrder.Keys);
order.Sort();

props = new List<PropertyInfo>();

order.ForEach(i => props.Add(propsOrder[i]));

PropLookup.Add(type, props);

更新 - 完整的 Linq

并使用完全 Linq 解决方案:

static IList<PropertyInfo> GetWritableProperties(Type type)
{
lock (SyncObj)
{
List<PropertyInfo> props;

if (!PropLookup.TryGetValue(type, out props))
{
props = type.GetProperties()
.Select(p => new { p, Atts = p.GetCustomAttributes(typeof(WriteableAttribute), inherit: true) })
.Where(p => p.Atts.Length != 0)
.OrderBy(p => ((WriteableAttribute)p.Atts[0]).Order)
.Select(p => p.p)
.ToList();

PropLookup.Add(type, props);
}

return props;
}
}

关于c# - 保证列表中属性的顺序与它们在代码文件中出现的顺序相匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7084206/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com