エンティティからのプロパティのセレクターとして機能する一般的な列定義クラスを設計しています。これはすべて、LOB アプリケーションでさまざまな側面のグリッド表示を管理しやすくするためです。
残念ながら、コレクションに含まれるクラスで汎用パラメーターを使用しようとして壁にぶつかりました。以下の SettingsContext クラスの実装例は、何が起こっているかを説明しています。
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T>: IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public class ColumnSet
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<object>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
// Cannot implicitly convert type 'DisplayColumn<System.Configuration.SettingsContext>' to 'IDisplayColumn<object>'.
// An explicit conversion exists (are you missing a cast?)
IDisplayColumn<object> testSingleColumn = new DisplayColumn<SettingsContext> {Title = "Test", Selector = x => x.Values };
// another test with other type used as a source which should be assignable to DisplayColumn<object>
testSingleColumn = new DisplayColumn<SettingsProvider> { Title="Another test", Selector = x => x.ApplicationName };
// Cannot implicitly convert type 'System.Collections.Generic.List<IDisplayColumn<System.Configuration.SettingsContext>>'
// to 'System.Collections.Generic.IEnumerable<IDisplayColumn<object>>'.
// An explicit conversion exists (are you missing a cast?)
var columnSets = new List<ColumnSet>
{
new ColumnSet
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext /* or object */>>
{
new DisplayColumn<SettingsContext> {Title = "Column 1", Order = 1, Selector = x => x.IsReadOnly },
new DisplayColumn<SettingsContext> {Title = "Column 2", Order = 2, Selector = x => x.IsSynchronized },
new DisplayColumn<SettingsContext> {Title = "Column 3", Order = 3, Selector = x => x.Keys }
}
}
};
}
}
共分散と反分散の目的をどのように理解するかは、これが実際に予想されることです.outパラメーターはIDisplayColumn testSingleColumn = new DisplayColumnの割り当てに使用する必要がありますが、Func inパラメーターをジェネリックにする必要があり、outは常にオブジェクトになります。
このようなシナリオを実装するには、カスタム Func を実装する必要がありますか、それとも dotnet がそのような目的に適した型を既に持っているのでしょうか?
現在、私が見ることができる唯一の解決策は、 Func< object, object > Selector プロパティを使用して非ジェネリック DisplayColumn クラスを作成し、各割り当てで引数を具体的な型にキャストすることですが、これは明らかに優れた解決策ではありません。もう 1 つのオプションは、ベースの非ジェネリック DisplayColumn クラスを継承し、ジェネリック セレクターを継承されたジェネリック クラスに配置することですが、データを表示するときにこの式を使用すると、継承されたジェネリック クラスでジェネリック メソッドを呼び出す必要があり、これはパフォーマンスとコードの品質基準では実際には受け入れられません。