C# 从接受动态参数作为输入的lambda获取属性名
我正在设计一个测试API。我想要一个API,比如:C# 从接受动态参数作为输入的lambda获取属性名,c#,.net,dynamic,lambda,C#,.net,Dynamic,Lambda,我正在设计一个测试API。我想要一个API,比如: // There is a dynamic object which should be tested to have certain properties. dynamic result = SomeMethod(); AssertPropertyIsNotNull(resut, o => o.Title); AssertPropertyIsNotNull(resut, o => o.City.Name); 我想编写TestP
// There is a dynamic object which should be tested to have certain properties.
dynamic result = SomeMethod();
AssertPropertyIsNotNull(resut, o => o.Title);
AssertPropertyIsNotNull(resut, o => o.City.Name);
我想编写TestProperty
方法来断言属性,并显示一条正确的消息它失败如下:
private void AssertPropertyIsNotNull(dynamic result, Func<dynamic, object> propertySelector)
{
var propertyPath = GetPropertyPathFromFunc(propertySelector);
var errorMessage = $"{propertyPath} is not filled properly."
Assert.IsNotNull(propertySelector(result), errorMessage);
}
private void AssertPropertyIsNotNull(动态结果,Func propertySelector)
{
var propertyPath=GetPropertyPathFromFunc(propertySelector);
var errorMessage=$“{propertyPath}未正确填充。”
IsNotNull(propertySelector(结果),errorMessage);
}
在本例中,我需要GetPropertyPathFromFunc
的主体
问题如何编写一个方法,以类似
o=>City.Name的lambda作为输入,并返回类似“City.Name”的字符串
结果。当您使用动态
时,您会松开类型安全和编译时成员名称检查,因此使用字符串作为属性名称没有任何区别
这里有一个解决方案。它需要大量的错误检查和异常处理。您还可以添加缓存机制以减少反射开销
public static bool IsPropertyNull(dynamic obj, string propertyName)
{
var path = propertyName.Split('.');
object tempObject = obj;
for (int i = 0; i < path.Length; i++)
{
PropertyInfo[] dynamicProperties = tempObject.GetType().GetProperties();
var property = dynamicProperties.Single(x => x.Name == path[i]);
tempObject = property.GetValue(tempObject);
}
return tempObject == null;
}
bool isTitleNull = IsPropertyNull(result, "Title");
bool isCityNameNull = IsPropertyNull(result, "City.Name");
公共静态bool IsPropertyNull(动态对象,字符串propertyName)
{
var path=propertyName.Split('.');
对象tempObject=obj;
for(int i=0;ix.Name==path[i]);
tempObject=property.GetValue(tempObject);
}
返回tempObject==null;
}
bool isTitleNull=IsPropertyNull(结果,“标题”);
bool iscitynameull=IsPropertyNull(结果为“City.Name”);
如前所述,不幸的是,动态
不能在C#编译器当前实现的表达式树中使用。作为替代方案,您可以使用收集访问的属性名称的自定义动态对象调用委托。我已经在下面演示了这一点。请注意,这只适用于您给出的有限语法,我没有花太多精力来处理更复杂的问题
private static string GetPropertyPathFromFunc(Func<dynamic, object> propertySelector)
{
var collector = new PropertyNameCollector();
propertySelector(collector);
return collector.Name;
}
private class PropertyNameCollector : DynamicObject
{
public string Name { get; private set; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!string.IsNullOrEmpty(Name))
Name += ".";
Name += binder.Name;
result = this;
return true;
}
}
私有静态字符串GetPropertyPathFromFunc(Func propertySelector)
{
var collector=新的PropertyNameCollector();
属性选择器(收集器);
返回收集器名称;
}
私有类PropertyNameCollector:DynamicObject
{
公共字符串名称{get;private set;}
公共重写bool TryGetMember(GetMemberBinder绑定器,输出对象结果)
{
如果(!string.IsNullOrEmpty(名称))
姓名+=”;
名称+=活页夹。名称;
结果=这个;
返回true;
}
}
?