任何人对是否有任何意见IEquatable<T>或IComparable<T>一般应要求T是sealed(如果是class)?
这个问题发生在我身上,因为我正在编写一组旨在帮助实现不可变类的基类.基类要提供的部分功能是自动实现相等比较(使用类的字段以及可应用于字段来控制相等比较的属性).当我完成时它应该是相当不错的 - 我正在使用表达式树为每个动态创建一个编译的比较函数T,因此比较函数应该非常接近正则相等比较函数的性能.(我使用键入的不可变字典System.Type和双重检查锁定以合理的方式存储生成的比较函数)
尽管如此,有一件事是用来检查成员字段相等性的函数.我的初衷是检查每个成员字段的类型(我将调用X)是否实现IEquatable<X>.但是,经过一番思考后,除非X是这样,否则我认为这是不安全的sealed.原因在于,如果X不是sealed,我无法确定是否X正确地将等式检查委托给虚拟方法X,从而允许子类型覆盖相等比较.
这就提出了一个更普遍的问题 - 如果一个类型没有被密封,它是否应该真正实现这些接口?我想不会,因为我认为接口契约是比较两种X类型,而不是两种类型,可能是也可能不是X(虽然它们当然必须是X或者是子类型).
你们有什么感想?应该IEquatable<T>和IComparable<T>避免对开封类?(也让我想知道是否有一个fxcop规则)
我现在的想法是让我产生比较功能只能用IEquatable<T>在成员字段,其T为sealed,而是用虚拟的Object.Equals(Object obj),如果T是密封的,即使T工具IEquatable<T>,因为该领域可能的潜在店亚型T和我怀疑的大多数实现IEquatable<T>适当设计的传承.
嗨,有没有人知道是否有任何内置的类从bindingexpression解析绑定对象,它的DataItem和属性路径?
我正在尝试为文本框编写Blend 3行为,该行为会自动调用绑定到文本框Text属性的对象上的方法.
文本框绑定到viewmodel类的属性.我想要做的是从绑定表达式解析viewmodel类,然后对此进行调用.
我首先从行为的关联对象中检索绑定表达式,如下所示:
private BindingExpression GetTextBinding()
{
return this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
}
Run Code Online (Sandbox Code Playgroud)
完成此操作后,如果我们查看绑定表达式,我们可以看到它通过绑定表达式的DataItem属性引用了数据上下文.
另外,我们有绑定表达式父绑定绑定的属性的相对路径.
所以,我们可以得到这些信息:
var bindingExpression = GetTextBinding();
object dataContextItem = bindingExpression.DataItem;
PropertyPath relativePropertyPath = bindingExpression.ParentBinding.Path;
Run Code Online (Sandbox Code Playgroud)
现在,这个属性路径可能是一个深度嵌套和复杂的路径,我非常希望避免(重新)实现解析.我已经搜索了.NET文档并用反射器围绕组件弹跳,但都无济于事 - 我找不到肯定必须存在的东西 - 必须有一些类来执行数据项目的路径解析(数据上下文).
有谁知道这可能存在的地方?有关解决绑定对象的替代方法的任何建议吗?
注意,我正在尝试获取绑定对象(绑定属性的父节点)(在本例中为字符串) - 我可以很容易地得到绑定值,但它是我需要的父节点.
在此先感谢您的帮助!菲尔
这个问题将表明我在实现/使用INotifyPropertyChanged时缺乏对预期行为的理解:
问题是 - 为了使绑定按预期工作,当你有一个本身实现INotifyPropertyChanged的类时,它具有类型为INotifyPropertyChanged的嵌套属性你是否希望在内部订阅这些属性的更改通知然后传播通知?或者预期绑定基础设施是否具备使其变得不必要的智能?
例如(注意这段代码不完整 - 只是为了说明问题):
public class Address : INotifyPropertyChanged
{
string m_street
string m_city;
public string Street
{
get { return m_street; }
set
{
m_street = value;
NotifyPropertyChanged(new PropertyChangedEventArgs("Street"));
}
}
public string City
{
get { return m_city; }
set
{
m_city = value;
NotifyPropertyChanged(new PropertyChangedEventArgs("City"));
}
}
public class Person : INotifyPropertyChanged
{
Address m_address;
public Address
{
get { return m_address = value; }
set
{
m_address = value;
NotifyPropertyChanged(new PropertyChangedEventArgs("Address"));
}
} …Run Code Online (Sandbox Code Playgroud) 好吧,这真的很烦人,之前我注意到WPF生成的用于加载XAML资源的代码似乎没有使用强名称,因此在需要支持并行版本的WPF程序集的情况下可能会出现问题.
事实证明是这样的,它现在给我带来了问题 - 我有一个插件系统,应该支持插件的并排安装,这些插件的版本号(它们的组装版本)不同.这当然可以由.NET支持,因为即使它们具有相同的DLL文件名,也确定程序集具有不同的标识,只要它们具有强名称并且具有不同的公钥/私钥或具有不同的程序集版本号.
现在,如果我们查看visual studio为windows和usercontrols生成的代码,我们会在自动生成的文件中看到以下内容:
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/Sensormatic.AMK1000.Panel;component/views/servicepanelui.xaml", System.UriKind.Relative);
#line 1 "..\..\..\Views\ServicePanelUI.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
Run Code Online (Sandbox Code Playgroud)
注意创建资源定位符的行 - 它使用的是相对URI,它不指定强名称或包含xaml资源的程序集的版本.
我想也许LoadComponent会检查调用程序集的标识并使用它的公钥和版本细节,或者可能检查包含'this'参数类型的程序集的标识.
看起来情况并非如此 - 如果您有两个具有不同版本号(但文件名相同)的程序集,那么您可以获得一个IOException,其中包含"无法找到资源X"的消息(对于上面的示例"无法找到资源"视图/ servicepanelui的.xaml".
更糟糕的是,我很确定这也意味着具有相同文件名但不同公钥/私钥的程序集(即来自不同的发布者)也会导致此错误.
那么,有谁知道怎么解决这个问题?如何使WPF强名称兼容.
请注意,就我而言,这是一个WPF错误.您不应该仅使用Appdomain隔离来避免这种情况.
为什么将T限制为类的泛型方法会在生成MSIL代码中有装箱指令?
我对此感到非常惊讶,因为由于T被约束为引用类型,因此生成的代码不需要执行任何装箱.
这是c#代码:
protected void SetRefProperty<T>(ref T propertyBackingField, T newValue) where T : class
{
bool isDifferent = false;
// for reference types, we use a simple reference equality check to determine
// whether the values are 'equal'. We do not use an equality comparer as these are often
// unreliable indicators of equality, AND because value equivalence does NOT indicate
// that we should share a reference type since it may be a mutable.
if (propertyBackingField != newValue)
{ …Run Code Online (Sandbox Code Playgroud) .net ×3
c# ×3
wpf ×2
boxing ×1
data-binding ×1
generics ×1
icomparable ×1
iequatable ×1
immutability ×1
mvvm ×1
resources ×1
sealed ×1
strongname ×1
xaml ×1