Ivy*_*ing 39 c# properties parameter-passing
我正在寻找一种方法将属性本身传递给一个函数.不是财产的价值.函数事先不知道哪个属性将用于排序.此示例中最简单的方法是:使用不同的参数类型创建4个覆盖.其他方式是使用typeof()内部功能.当Class1具有数百个属性时,这两种方式都是不可接受的.到目前为止我找到了以下方法:
class Class1
{
string vehName;
int maxSpeed;
int fuelCapacity;
bool isFlying;
}
class Processor
{
List<Class1> vehicles = null;
Processor(List<Class1> input)
{
vehicles = input;
}
List<Class1> sortBy(List<Class1> toSort, string propName)
{
if (toSort != null && toSort.Count > 0)
{
return toSort.OrderBy(x => typeof(Class1).GetProperty(propName).GetValue(x, null)).ToList();
}
else return null;
}
}
class OuterUser
{
List<Class1> vehicles = new List<Class1>();
// ... fill the list
Processor pr = new Processor(vehicles);
List<Class1> sorted = pr.sortBy("maxSpeed");
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢这种方法,因为在将字符串传递给处理函数时存在"人为错误"的风险.当字符串由代码的其他部分生成时,这将变得更加丑陋.请提出更优雅的方法来实现Class1属性的传递以进行进一步处理.使用恕我直言的最佳选择(或类似的东西):
vehicles = sortBy(vehicles, Class1.maxSpeed);
Run Code Online (Sandbox Code Playgroud)
Oli*_*bes 60
您可以将属性访问器传递给该方法.
List<Class1> SortBy(List<Class1> toSort, Func<Class1, IComparable> getProp)
{
if (toSort != null && toSort.Count > 0) {
return toSort
.OrderBy(x => getProp(x))
.ToList();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
var result = SortBy(toSort, x => x.maxSpeed);
Run Code Online (Sandbox Code Playgroud)
但是你可以更进一步,编写自己的扩展方法.
public static class CollectionExtensions
{
public static List<TSource> OrderByAsListOrNull<TSource, TKey>(
this ICollection<TSource> collection, Func<TSource,TKey> keySelector)
if (collection != null && collection.Count > 0) {
return collection
.OrderBy(x => keySelector(x))
.ToList();
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以这样排序
List<Class1> sorted = toSort.OrderByAsListOrNull(x => x.maxSpeed);
Run Code Online (Sandbox Code Playgroud)
但是也
Person[] people = ...;
List<Person> sortedPeople = people.OrderByAsListOrNull(p => p.LastName);
Run Code Online (Sandbox Code Playgroud)
请注意,我声明了第一个参数,ICollection<T>因为它必须满足两个条件:
Count属性IEnumerable<T>能够应用LINQ方法OrderBy.List<Class1>是一个ICollection<T>,但也阵列Person[]许多其他集合.
到目前为止,我已经展示了如何阅读房产.如果该方法需要设置属性,则还需要将其传递给setter委托
void ReadAndWriteProperty(Func<Class1, T> getProp, Action<Class1, T> setProp)
Run Code Online (Sandbox Code Playgroud)
T物业的类型在哪里.
Mat*_*asG 27
您可以使用lambda表达式来传递属性信息:
void DoSomething<T>(Expression<Func<T>> property)
{
var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
if (propertyInfo == null)
{
throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
DoSomething(() => this.MyProperty);
Run Code Online (Sandbox Code Playgroud)
我从@ MatthiasG的答案中找不到的是如何获得属性值而不仅仅是它的名称.
public static string Meth<T>(Expression<Func<T>> expression)
{
var name = ((MemberExpression)expression.Body).Member.Name;
var value = expression.Compile()();
return string.Format("{0} - {1}", name, value);
}
Run Code Online (Sandbox Code Playgroud)
使用:
Meth(() => YourObject.Property);
Run Code Online (Sandbox Code Playgroud)
很棒的解决方案在这里...
void GetString<T>(string input, T target, Expression<Func<T, string>> outExpr)
{
if (!string.IsNullOrEmpty(input))
{
var expr = (MemberExpression) outExpr.Body;
var prop = (PropertyInfo) expr.Member;
prop.SetValue(target, input, null);
}
}
void Main()
{
var person = new Person();
GetString("test", person, x => x.Name);
Debug.Assert(person.Name == "test");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
51169 次 |
| 最近记录: |