Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么应该返回DynamicMetaObject.BindGetMember的结果表达式来表示该成员不存在?_C#_Wpf_Dynamic - Fatal编程技术网

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)
return
null
如果没有与名称匹配的子/命令

这里发生的是,如果我在XAML中绑定一个不存在的子/命令名,那么绑定将成功解析为
null

但是,我希望的行为是绑定无法成功解析。原因是它允许我使用
PriorityBinding

到目前为止,我有两种解决方案:

  • 如果没有匹配的子/命令名,则引发RuntimeBinderException。当您尝试访问无效成员时,
    动态
    对象就是这样做的。但我觉得这里有点太重了
  • 返回dependencProperty.unset值,该值足以使
    PriorityBinding
    工作(如中所述)
但是,这些解决方案都不会导致通常的绑定错误消息:

System.Windows.Data警告:40:BindingExpression路径错误:'**' 在“对象”“对象”(HashCode=13794971)上找不到属性。 BindingExpression:Path=**;DataItem='Object'(HashCode=13794971); 目标元素为“TextBlock”(名称=“”);目标属性为“Text” (键入“字符串”)


那么,关于实现这一行为的最佳方法有什么想法/建议吗?

据我所知,最接近你的是:

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
方法。