[英]How do I use my own reference types as the data type of a dataview column
我有一個包含列的 DataTable,其中一些列的數據類型是我的項目中的 class 的類型,因此該列將被添加到表中:
DataColumn column = _dataTable.Columns.Add("myColumnName", typeof(MyClass));
當我從 DataTable 創建 DataView 並嘗試設置 RowFilter 時出現問題:
_dataView.RowFilter = "[myColumnName] = \"xyz\"";
這會引發異常“無法對 MyClass 和 System.String 執行 '=' 操作”。
MyClass 實現了 IComparable 以及 Equals(object obj)、ToString() 以及所有相等和比較運算符,但這顯然還不夠。 我什至嘗試將條件分支添加到 CompareTo(object obj) 以接受一個字符串 obj,但無濟於事,它甚至從未命中 CompareTo。
大概 DataView 中的表達式解析器根本無法弄清楚如何將 MyClass 與字符串進行比較。
我將不勝感激任何建議。
根據 Cee McSharpFace 的要求,這是我的 class 的相關部分:
public class PartNumber : IXmlSerializable, IComparable<PartNumber>, IArithmetic, IEquatable<PartNumber>, IEquatable<string>, IComparable<string>
{
public int CompareTo(PartNumber other)
{
int result = 0;
if (other is null)
{
result = 1;
}
else
{
DoActualComparison(other);
}
return result;
}
public int CompareTo(string other)
{
return ToString().CompareTo(other);
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public override bool Equals(object obj)
{
return !(obj is null) &&
obj is PartNumber &&
this == ((PartNumber)obj);
}
public static bool operator ==(PartNumber x, PartNumber y)
{
return x.CompareTo(y) == 0;
}
public static bool operator !=(PartNumber x, PartNumber y)
{
return !(x == y);
}
public static bool operator >(PartNumber x, PartNumber y)
{
return x.CompareTo(y) > 0;
}
public static bool operator <(PartNumber x, PartNumber y)
{
return x.CompareTo(y) < 0;
}
public bool Equals(string other)
{
return ToString().Equals(other);
}
public bool Equals(PartNumber other)
{
return Equals((object)other);
}
public static bool operator ==(PartNumber lhs, string rhs)
{
return lhs.ToString() == rhs;
}
public static bool operator !=(PartNumber lhs, string rhs)
{
return lhs.ToString() != rhs;
}
public object Add(object x)
{
return this;
}
public object Subtract(object x)
{
return this;
}
public object Multiply(object x)
{
return this;
}
public object Divide(object x)
{
return this;
}
public override string ToString()
{
return MakeObjectIntoString();
}
}
具有PartNumber
類型的列映射到數據表中的內部StorageType.Object
。
二元運算評估器不支持此存儲類型上的任何運算符:
參考源,這是它拋出異常的地方。 支持的類型列表列在 switch 語句后面幾十行。
解決方法 1:
添加第二列,在其中僅存儲PartNumber.ToString()
結果(預先計算)以在查詢中使用。
為了使您的代碼編譯並用於演示屬性,我為部件號添加了一個私有字符串字段,我在其ToString
覆蓋中返回:
public struct PartNumber : IComparable<PartNumber>, IEquatable<PartNumber>, IEquatable<string>, IComparable<string>
{
private readonly string actualPartnumber;
public PartNumber(string samplePartnumber) => this.actualPartnumber = samplePartnumber;
/* ... */
public override string ToString() => actualPartnumber;
}
用法:
var dataTable = new DataTable();
var column = dataTable.Columns.Add("myColumnName", typeof(PartNumber));
var columnStr = dataTable.Columns.Add("myColumnNameStr", typeof(String));
var newRow1 = dataTable.NewRow();
newRow1["myColumnName"] = new PartNumber("abc");
newRow1["myColumnNameStr"] = newRow1["myColumnName"].ToString();
dataTable.Rows.Add(newRow1);
var newRow2 = dataTable.NewRow();
newRow2["myColumnName"] = new PartNumber("xyz");
newRow2["myColumnNameStr"] = newRow2["myColumnName"].ToString();
dataTable.Rows.Add(newRow2);
var dataView = new DataView(dataTable)
{
RowFilter = "[myColumnNameStr] = 'xyz'"
};
Console.WriteLine(dataView.Count);
--> 如您所料,這將返回一行。
解決方法 2
Convert function可以處理StorageType.Object
並且能夠正確使用其ToString
將PartNumber
實例轉換為字符串。 所以這也可以:
var dataTable = new DataTable();
dataTable.Columns.Add("myColumnName", typeof(PartNumber));
var newRow1 = dataTable.NewRow();
newRow1["myColumnName"] = new PartNumber("abc");
dataTable.Rows.Add(newRow1);
var newRow2 = dataTable.NewRow();
newRow2["myColumnName"] = new PartNumber("xyz");
dataTable.Rows.Add(newRow2);
var dataView = new DataView(dataTable)
{
RowFilter = "CONVERT([myColumnName], System.String) = 'xyz'"
};
Console.WriteLine(dataView.Count);
--> 我測試了它,它也返回了正確的(也是唯一的)匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.