c#属性数组
本文关键字:数组 属性 | 更新日期: 2023-09-27 18:03:04
我有几个get属性,我希望能够像函数数组一样循环。我希望能够做这样的事情
public int prop1 { get; }
public string prop2 { get; }
public int[] prop3 { get; }
public int prop4 { get; }
public string prop5 { get; }
public string prop6 { get; }
Func<var> myProperties = { prop1, prop2, prop3, prop4, prop5, prop6 };
ArrayList myList = new ArrayList();
foreach( var p in myProperties)
{
myList.Add(p);
}
这段代码非常糟糕,但我认为它传达了我想要能够做的事情的想法。有人知道我该怎么做吗?
您可以使用反射来访问类型中的属性:
class MyType
{
public int prop1 { get; }
public string prop2 { get; }
public int[] prop3 { get; }
public int prop4 { get; }
public string prop5 { get; }
public string prop6 { get; }
public List<string> GetAllPropertyValues()
{
List<string> values = new List<string>();
foreach (var pi in typeof(MyType).GetProperties())
{
values.Add(pi.GetValue(this, null).ToString());
}
return values;
}
}
请注意,反射很慢,如果有更好的方法,你不应该使用它。例如,当您知道只有6个属性时,只需逐个查看它们。
如果您已经知道要循环遍历的所有属性,那么您可以尝试使用
List<Reflection.PropertyInfo> myProperties = new List()<object>
{
typeof(SomeType).GetProperty("prop1"),
typeof(SomeType).GetProperty("prop2"),
typeof(SomeType).GetProperty("prop3"),
typeof(SomeType).GetProperty("prop4"),
typeof(SomeType).GetProperty("prop5"),
typeof(SomeType).GetProperty("prop6")
};
foreach(var p in myProperties)
{
var value = p.GetValue(someObject, new object[0]);
myList.Add(p);
}
如果没有,你可以这样写:
var myProperties =
from pi in someObject.GetType().GetProperties()
select new
{
pi.Name,
Value = pi.GetValue(object, new object[0])
};
foreach(var p in myProperties)
{
myList.Add(p.Value);
}
您可以尝试使用GetProperties
getproperty文档
的例子:
PropertyInfo[] myPropertyInfo;
// Get the properties of 'Type' class object.
myPropertyInfo = Type.GetType("System.Type").GetProperties();
Console.WriteLine("Properties of System.Type are:");
for (int i = 0; i < myPropertyInfo.Length; i++)
{
Console.WriteLine(myPropertyInfo[i].ToString());
}
进一步信息:
带有标志的GetProperties示例非常好,如果您想访问属性的特定子集(例如Public Properties)
代码离工作还很远。myProperties
变量应该是一个数组,您需要创建从属性中读取的函数。(属性getter实际上是作为函数实现的,但你不能作为函数调用它或获取对它的引用。)然后通过调用它们来使用它们。
public class MyClass {
public int prop1 { get; set; }
public string prop2 { get; set; }
public int[] prop3 { get; set; }
public int prop4 { get; set; }
public string prop5 { get; set; }
public string prop6 { get; set; }
public ArrayList GetProperties() {
Func<object>[] myProperties = {
() => prop1, () => prop2, () => prop3,
() => prop4, () => prop5, () => prop6
};
ArrayList myList = new ArrayList();
foreach (var p in myProperties) {
myList.Add(p());
}
return myList;
}
}
如果你需要你的数组属性,因为你需要(像我一样)设置和/或获取几个相关的(和相同类型的)属性,这里是你可以做的。我知道反射是"慢"的,但是对于我的用例来说,减少重复代码(以及因此产生的错误机会)的好处远远超过反射带来的任何"慢"(这是微不足道的)。这并不处理索引属性,但可以很容易地从它创建一个版本。
'公共类MyClass{
private string[] myBoolPropertyNames =
{
nameof(MyBool1Property),
nameof(MyBool2Property)
}; // MyBoolPropertyNames =
private MyClass()
{
foreach (var propertyName in myBoolPropertyNames)
{
ReflectionHelper.SetPropertyValue
(
parentObject: this,
propertyName: propertyName,
untypedPropertyValue: true
); // SetPropertyValue
} // foreach (var propertyName in myBoolPropertyNames)
foreach (var propertyName in myBoolPropertyNames)
{
bool boolPropertyValue = ReflectionHelper.GetPropertyValue<bool>
(
parentObject: this,
propertyName: propertyName
); // SetPropertyValue
Console.WriteLine($"Property '{propertyName}' value: {boolPropertyValue}");
} // foreach (var propertyName in myBoolPropertyNames)
}
public bool MyBool1Property { get; set; }
public bool MyBool2Property { get; set; }
} // MyClass
'公共类ReflectionHelper{
public static PropertyType GetPropertyValue<PropertyType>
(
object parentObject,
string propertyName
)
{
if (parentObject == null)
{
throw new ArgumentException
(
$"Missing '{nameof(parentObject)}'."
);
} // if (parentObject == null)
PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
if (propertyInfo == null)
{
throw new ArgumentException
(
"No PropertyInfo found for Property: " + propertyName
);
} // if (propertyInfo == null)
object untypedPropertyValue = propertyInfo.GetValue(obj: parentObject);
Type propertyType =
(
Nullable.GetUnderlyingType(propertyInfo.PropertyType)
?? propertyInfo.PropertyType
); // propertyType =
object typedPropertyValue =
(
(untypedPropertyValue == null)
? null
: Convert.ChangeType(untypedPropertyValue, propertyType)
); // typedPropertyValue =
return (PropertyType)typedPropertyValue;
} // GetPropertyValue
public static void SetPropertyValue
(
object parentObject,
string propertyName,
object untypedPropertyValue
)
{
if (parentObject == null)
{
throw new ArgumentException
(
$"Missing '{nameof(parentObject)}'."
);
} // if (parentObject == null)
PropertyInfo propertyInfo = parentObject.GetType().GetProperty(propertyName);
if (propertyInfo == null)
{
throw new ArgumentException
(
"No PropertyInfo found for Property: " + propertyName
);
} // if (propertyInfo == null)
Type propertyType =
(
Nullable.GetUnderlyingType(propertyInfo.PropertyType)
?? propertyInfo.PropertyType
); // propertyType =
object typedPropertyValue =
(
(untypedPropertyValue == null)
? null
: Convert.ChangeType(untypedPropertyValue, propertyType)
); // typedPropertyValue =
propertyInfo.SetValue
(
obj: parentObject,
value: typedPropertyValue
); // propertyInfo.SetValue
} // SetPropertyValue
} // ReflectionHelper
"
您可以使用数组缓冲区并从中获取所有道具。通过这种方式,您可以非常快速地获取和设置:
public object[] buf = new object[5];
public int prop1 { get => buf[0]; }
public string prop2 { get => buf[1]; }
public int[] prop3 { get => buf[2]; }
public int prop4 { get => buf[3]; }
public string prop5 { get => buf[4]; }
public string prop6 { get => buf[5]; }
现在可以访问所有道具与buf
:
foreach (var item in buf) {
myList.Add(item);
}
或直接访问:
buf[1] = 10;
x = buf[1];