如何创建一个自定义的*写*仅依赖属性?(How can I create a custom *wri

2019-08-02 03:42发布

我需要知道程序是什么制造一个只写依赖属性。 我可以看到的DependencyProperty类没有对只写属性的特殊“注册”的方法,但我不知道该RegisterAttached方法是否可以申请什么,我试图做的。

这个属性需要一个依赖属性,而不是一个简单的CLR属性。 在内部,我的课需要在该物业的PropertyChangedCallback才能保持稳定。

我知道,只写依赖的属性可以被创建,因为它是在规定很清楚:
临C#2008和.NET 3.5平台,页1061 。
但是,这是我甚至可以找到“依赖属性”,并在同一页上“只写”的唯一地方。 而这个作者显然没有想到居然读者展示了比基本读写依赖属性之外的任何程序是必要的。 当然,这本书是BS的负载-但是这本书看起来很标准,所以我觉得这是一个非常安全的赌注,作者是正确的。 我认为在互联网上的信息缺乏的事实,没有人通常需要做出这样的特性造成的。

我知道这听起来很可疑想使自己只写依赖属性。 我向你保证,这是有道理的,我想它。 我班有其值是只对对象设置有用的属性。 如果另一个对象后来请求此属性的值,就不能作出任何合理的常理出价值的不知道的setter的原始环境。

此属性不打算用于参考。 让外界物体尝试使用属性值这种方式是有问题的,危险的,存在安全隐患。 所以我相信最好的设计是禁止此属性的读取操作。 任何使用我的班会发现,他们被迫使用类它的目的的方式,这将制定出到底有多大更好,更洁净。

Answer 1:

你不能,这似乎是由设计。 虽然我能理解你的做法所提到的书,我绝不质疑它的品质,我仍然相信这是某种形式的复制和粘贴或类似的问题。 这里是我的推理:

WPF属性系统代码

  • 正如你已经提到的公共API 的DependencyProperty类只拥有RegisterReadOnly()和RegisterAttachedReadOnly() 。
  • 在通过类的内部Speluncing 反射器只揭示了处理这些专用代码只读依赖属性 ,没有什么迹象就只写功能。
  • 另一种选择可能是元数据,但也依赖项属性的元数据 ,也没有特别框架属性元数据由手段FrameworkPropertyMetadataOptions枚举是提供沿只写线条东西。

WPF属性系统设计

  • 更重要的是,“目前执行WPF XAML其处理器的本质上是依赖属性认识。 加载是依赖属性二进制XAML和处理属性时,WPF XAML处理器使用属性系统方法依赖属性。 这有效地绕过了产权包装“。 见XAML加载和依赖项属性 。
  • 最重要的是,“依赖属性一般应被认为是公共属性。 为Windows Presentation Foundation(WPF)属性系统的性质阻碍作出关于依赖属性值的安全保障能力“。 请参阅相关财产安全 。

尤其是后两个点勾勒出设计约束,这种依赖的属性值始终可以访问通过的GetValue() / 的SetValue() ,不管他们的CLR包装是否有访问限制或可在所有,唯一的例外是专门占只读依赖属性 。

因此,随着杰夫斯的回答已经暗示,只删除例如,吸气并没有真正阻止任何人访问通过属性的GetValue() ,虽然这至少可以“减少一个自定义类的立即暴露命名空间”。 使所建议的属性值稍差可见/访问和检索值本身无用,为客户的任何这样的语义解决方法的有效性杰夫取决于当然您的特定情况。



Answer 2:

有趣的是,这绝对是一个罕见的情况下,我很想听到更多的是什么使。

你会考虑提供一个无效的值(如空)的思想,通过结合或读取的GetValue,而只是没有一个CLR消气?

无论是使用一个专用的DependencyProperty来存储您所关心的“真实”的价值, 或者只是一个私有成员变量。

在属性更改回调,随时还原值回原始值,同时存储离开所设定的新的价值。

我花了我大部分时间在做Silverlight控件的开发,所以这个属性在WPF和Silverlight的土地工作,并且不使用coercian或任何乐趣这样。 也许它可以让你要在正确的轨道上,虽然。

    /// <summary>
    /// Sets the write-only dependency property.
    /// </summary>
    public string MyWriteOnlyDependencyProperty
    {
        set { SetValue(MyWriteOnlyDependencyPropertyProperty, value); }
    }

    private string _theRealSetValue;

    private bool _ignorePropertyChange;

    /// <summary>
    /// Identifies the MyWriteOnlyDependencyProperty dependency property.
    /// </summary>
    public static readonly DependencyProperty MyWriteOnlyDependencyPropertyProperty =
        DependencyProperty.Register(
            "MyWriteOnlyDependencyProperty",
            typeof(string),
            typeof(TemplatedControl1),
            new PropertyMetadata(null, OnMyWriteOnlyDependencyPropertyPropertyChanged));

    /// <summary>
    /// MyWriteOnlyDependencyPropertyProperty property changed handler.
    /// </summary>
    /// <param name="d">TemplatedControl1 that changed its MyWriteOnlyDependencyProperty.</param>
    /// <param name="e">Event arguments.</param>
    private static void OnMyWriteOnlyDependencyPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        TemplatedControl1 source = d as TemplatedControl1;
        if (source._ignorePropertyChange)
        {
            source._ignorePropertyChange = false;
            return;
        }
        string value = e.NewValue as string;

        source._theRealSetValue = value;

        // Revert, since this should never be accessible through a read
        source._ignorePropertyChange = true;
        source.SetValue(e.Property, e.OldValue);
    }


Answer 3:

它看起来像您可以使用CoerceValueCallback通过该属性相关联FrameworkPropertyMetadata在依赖属性定义应用。 只要安装一个回调通过自己只写机制需要第二个参数,新的值,并将其传递到目标,然后返回null (或值类型, default(T)

这是真的,“ NET记得之前强制原始值”,但它不会通过数据绑定传播。 调用GetValue将返回强制值,这不泄漏任何东西。

我用这个来实现我的首要属性,这是一个字节序列的价值单向方便制定者。 用户可以结合的字符串,例如,以设置主媒体资源到已编码的字节(ASCII或UTF-8,这取决于设置什么属性)。 但是,并非所有的字节序列是有效的UTF-8,所以这是不可能扭转转换和读取的字符串返回通过便利性。

public string AsciiData
{
    set { BinaryArray = Encoding.ASCII.GetBytes(value); }
}

public static readonly DependencyProperty AsciiDataProperty =
    DependencyProperty.Register("AsciiData",
        typeof(string),
        typeof(HexView),
        new FrameworkPropertyMetadata(null, CoerceAsciiData));

private static object CoerceAsciiData(DependencyObject target, object value)
{
    (target as HexView).AsciiData = value as string;
    return null;
}

胁迫处理程序可以通过元数据替换被删除,所以这是不提供安全性 ,但它会阻止开发商在错误的方法创建意外耦合。



Answer 4:

我很困惑,为什么你不能只是有“得到”不返回任何有用吗?

但是,另外,也许你只是不落实“OnMyWriteOnlyDependencyPropertyPropertyChanged”,在杰夫的例子。

没有真正的理由有情况下,如果没有人能读它,对吗?



文章来源: How can I create a custom *write-only* dependency-property?