C# 什么应该返回DynamicMetaObject.BindGetMember的结果表达式来表示该成员不存在?
我有一个(简化的)类,它具有通过C# 什么应该返回DynamicMetaObject.BindGetMember的结果表达式来表示该成员不存在?,c#,wpf,dynamic,C#,Wpf,Dynamic,我有一个(简化的)类,它具有通过IDynamicMetaObjectProvider公开的动态成员: public abstract class MyDynViewModel: ViewModelBase, IDynamicMetaObjectProvider { public DynamicMetaObject GetMetaObject(Expression parameter) { return new MyDynViewModelDynamicMetaOb
IDynamicMetaObjectProvider
公开的动态成员:
public abstract class MyDynViewModel: ViewModelBase, IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new MyDynViewModelDynamicMetaObject(parameter, this);
}
public object GetDynamicObject(string name)
{
return GetChild(name) ?? GetCommand(name);
}
}
以下是我的(简化)BindGetMember
方法:
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var self = Expression.Convert(Expression, LimitType);
Expression expression;
var propertyName = binder.Name;
var args = new Expression[1];
args[0] = Expression.Constant(propertyName);
expression = Expression.Call(self, typeof(MyDynViewModel).GetMethod("GetDynamicObject", BindingFlags.Public | BindingFlags.Instance), args);
var getMember = new DynamicMetaObject(expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType));
return getMember;
}
基本上,GetChild(string)
和GetCommand(string)
returnnull
如果没有与名称匹配的子/命令
这里发生的是,如果我在XAML中绑定一个不存在的子/命令名,那么绑定将成功解析为null
值
但是,我希望的行为是绑定无法成功解析。原因是它允许我使用PriorityBinding
到目前为止,我有两种解决方案:
- 如果没有匹配的子/命令名,则引发RuntimeBinderException。当您尝试访问无效成员时,
对象就是这样做的。但我觉得这里有点太重了动态
- 返回dependencProperty.unset值,该值足以使
工作(如中所述)PriorityBinding
那么,关于实现这一行为的最佳方法有什么想法/建议吗?据我所知,最接近你的是:
System.Windows.Data错误:17:无法从“”(类型“Test”)获取“EX”值(类型“Object”)。BindingExpression:Path=EX;DataItem='Test'(HashCode=11280399);目标元素为“TextBlock”(名称=“”);目标属性为“Text”(类型为“String”)InvalidOperationException:“System.InvalidOperationException:属性路径无效。”System.Dynamic.DynamicObject+MetaDynamic没有名为“Items”的公共属性。
现在,这个问题有多棘手。我看到你有相当复杂的代码,那是因为你从零开始创建所有东西。你有没有考虑过:
public class TestViewModel : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
return false; // if we didn't find member.
}
}
相反
如果这不符合您的需要,首先,您需要使用额外的参数“result”修改GetDynamicObject
签名
您需要将功能包装在表达式中,即伪代码:
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var self = Expression.Convert(Expression, LimitType);
Expression expression;
var propertyName = binder.Name;
var args = new Expression[1];
args[0] = Expression.Constant(propertyName);
expression = Expression.Call(self, typeof(MyDynViewModel).GetMethod("GetDynamicObject", BindingFlags.Public | BindingFlags.Instance), args);
expression = "if GetDynamicObject returned false, means we found nothing.
then we should return binder.FallbackGetMember(this, e)";
var getMember = new DynamicMetaObject(expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType));
return getMember;
}
您可以检查并跟踪DLR的实施情况:
// Define other methods and classes here
// 6. IDynamicMetaObjectProvider
// This supports the DLR's dynamic objects
if (accessor == null &&
SystemCoreHelper.IsIDynamicMetaObjectProvider(item))
{
accessor = SystemCoreHelper.NewDynamicPropertyAccessor(
item.GetType(), propertyName);
}
我无法从DynamicObject
继承,因为我已经从一个无法修改的基类继承。我成功地让它工作了,谢谢!我愿意做一些与您的答案类似的事情,但是我缺少了当路径无效时要调用的binder.FallbackGetMember
方法。