- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在设计一个通用的列定义类,它将充当实体属性的选择器,所有这些都是为了更容易管理 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 类,并在每个赋值中将参数转换为具体类型,这显然不是一个很好的解决方案。另一种选择是继承基类非泛型 DisplayColumn 类并将泛型选择器放在继承的泛型类中,但是在呈现数据时使用此表达式需要调用继承的泛型类中的泛型方法,这对于性能和代码质量标准来说确实是 Not Acceptable 。
最佳答案
如果您也使 ColumnSet 成为通用的,那么您可以指定用于它返回的可枚举列的类型。下面的代码将编译,我想实现你所追求的。
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<T>
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<T>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
IDisplayColumn<SettingsContext> testSingleColumn = new DisplayColumn<SettingsContext> { Title = "Test", Selector = x => x.Values };
var columnSets = new List<ColumnSet<SettingsContext>>
{
new ColumnSet<SettingsContext>
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext>>
{
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 }
}
}
};
}
关于c# - 对 Func<T, object> 选择器属性使用逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19090297/
COW 不是奶牛,是 Copy-On-Write 的缩写,这是一种是复制但也不完全是复制的技术。 一般来说复制就是创建出完全相同的两份,两份是独立的: 但是,有的时候复制这件事没多大必要
我是一名优秀的程序员,十分优秀!