簡體   English   中英

如何使用我自己的引用類型作為數據視圖列的數據類型

[英]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並且能夠正確使用其ToStringPartNumber實例轉換為字符串。 所以這也可以:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM