c# - 为派生类的类型静态定义选项
问题描述
我正在开发一个框架,其中从框架的抽象类继承的类需要能够为它在调用 DoStuff() 时可以接受的选项指定模式。
我从一个抽象的 GetOptionsSchema() 方法开始,如下所示:
public abstract class Widget
{
public abstract OptionsSchema GetOptionsSchema();
public abstract void DoStuff(Options options);
}
然后其他开发人员将通过创建自定义 Widget 类型来扩展我的框架:
public abstract class FooWidget: Widget
{
public overide DoStuff(Options options)
{
//Do some FooWidget stuff
}
public overide OptionsSchema GetOptionsSchema()
{
//Return options for FooWidget
}
}
这可行,但需要框架创建每个 Widget 类型的实例以确定它们接受的选项模式,即使它实际上不需要 DoStuff() 使用这些类型中的任何一种。
最终,我希望能够直接从 System.Type 确定特定 Widget 类型的选项架构。我会创建一个自定义的 OptionsSchema 属性,但是构造这些模式更复杂,然后在属性的构造函数中进行。它需要在一个方法中发生。
我已经看到其他框架通过创建自定义属性来解决类似的问题,该属性通过名称标识静态方法或属性。例如 NUnit 中的TestCaseSource属性。
此选项可能如下所示:
public abstract class Widget
{
public abstract void DoStuff(Options options);
}
[OptionsSchemaSource(nameof(GetOptionsSchema))]
public abstract class FooWidget: Widget
{
public overide DoStuff(Options options)
{
//Do some FooWidget stuff
}
public static OptionSchema GetOptionsSchema()
{
//Return options for FooWidget
}
}
我喜欢 OptionsSchemaSource 属性如何使直接从 System.Type 获取选项模式成为可能,但这对于创建自定义 Widget 类型的其他开发人员来说似乎也不太容易发现。
使用抽象方法,另一个 Widget 开发人员知道他们必须重写 GetOptionSchema(),因为否则他们的代码将无法编译。使用 OptionsSchemaSource 属性,我能做的最好的事情是希望人们阅读我的文档并让框架在运行时遇到没有 OptionsSchemaSource 属性的 Widget 时抛出异常。
是否有替代/更好/推荐的方法?
解决方案
目前无法在编译时强制执行该属性;这将是您的用例的理想选择。也不可能有abstract static
方法,或者在接口中指定静态方法;所以没有办法确保该方法在编译时确实存在,除非通过抽象类或接口强制实例方法(这将需要该类型的实例才能访问)。
我会选择属性的想法——期望开发人员阅读文档并不是不合理的;即使重写了抽象方法,开发人员也需要知道如何OptionSchema
在重写的方法中构造一个 - 回到文档!
推荐阅读
- java - Play 商店中的 Android Kotlin 应用程序崩溃:类型 kotlin.Pair 不存在。java.lang.TypeNotPresentException
- soap - 有时会抛出 SAAJMetaFactoryImpl not found
- amazon-web-services - 无法 scp 到 EC2 实例,但可以 SSH
- react-native - 我无法在 react native cli 项目中安装新版本(3.0.7)的 native-base
- php - 函数存储未保存在数据库 laravel 8 中
- javascript - 捕获块不会被解雇
- reactjs - “IntrinsicAttributes”类型上不存在属性“商店”
- oracle - 复制活动需要更多时间才能将数据从本地 Oracle 数据库复制到 Azure Synapse Analytics
- html - 如何对图像产生这种效果
- mysql - 为什么这个 Javascript 函数会重写一个 div 的 innerHTML 而不是另一个?