C# 静态定义派生类类型的选项

C# 静态定义派生类类型的选项,c#,.net,attributes,static-methods,C#,.net,Attributes,Static Methods,我正在开发一个框架,其中从框架的抽象类继承的类需要能够为调用DoStuff()时可以接受的选项指定模式 我从一个抽象的getOptionSchema()方法开始,如下所示: 公共抽象类小部件 { 公共抽象选项Schema GetOptions Schema(); 公开摘要无效文件(选项); } 然后,其他开发人员将通过创建自定义小部件类型来扩展我的框架: 公共抽象类FooWidget:Widget { 公共过边卷帘(选项) { //做些食物小工具 } 公共覆盖选项架构GetOptions架构(

我正在开发一个框架,其中从框架的抽象类继承的类需要能够为调用DoStuff()时可以接受的选项指定模式

我从一个抽象的getOptionSchema()方法开始,如下所示:

公共抽象类小部件
{
公共抽象选项Schema GetOptions Schema();
公开摘要无效文件(选项);
}
然后,其他开发人员将通过创建自定义小部件类型来扩展我的框架:

公共抽象类FooWidget:Widget
{
公共过边卷帘(选项)
{
//做些食物小工具
}
公共覆盖选项架构GetOptions架构()
{
//FooWidget的返回选项
}
}
这是可行的,但需要框架为每种小部件类型创建一个实例,以确定它们接受的选项模式,即使它不需要实际使用任何这些类型的DoStuff()

最后,我希望能够直接从System.type确定特定小部件类型的选项模式。我将创建一个定制的optionSchema属性,但是构造这些模式比在属性的构造函数中进行更复杂。它需要以一种方式发生

我见过其他框架通过创建一个自定义属性来解决类似的问题,该属性通过名称标识静态方法或属性。例如NUnit中的属性

以下是此选项的外观:

公共抽象类小部件
{
公开摘要无效文件(选项);
}
[OptionSchemaSource(名称(GetOptionSchema))]
公共抽象类FooWidget:Widget
{
公共过边卷帘(选项)
{
//做些食物小工具
}
公共静态选项schema getoptionschema()
{
//FooWidget的返回选项
}
}
我喜欢optionSchemaSource属性使直接从System.Type获取选项模式成为可能,但对于创建自定义小部件类型的其他开发人员来说,这似乎也不太容易发现

使用抽象方法,另一个小部件开发人员知道他们必须重写GetOptionSchema(),因为否则他们的代码将无法编译。使用optionSchemaSource属性,我能做的最好的事情就是希望人们阅读我的文档,如果框架遇到没有optionSchemaSource属性的小部件,就让它在运行时抛出异常


是否有替代/更好/推荐的方法?

目前无法在编译时强制执行该属性;这对于您的用例来说是理想的。也不可能有
抽象静态
方法,或者在接口中指定静态方法;因此,除了通过抽象类或接口(需要该类型的实例才能访问)强制执行实例方法外,无法确保该方法在编译时实际存在


我同意属性的观点——期望开发人员阅读文档并不是不合理的;即使覆盖了一个抽象方法,开发人员也需要知道如何在被覆盖的方法中构造一个
选项schema
——回到文档

你几乎已经知道了所有你感兴趣的事情,来判断什么是最好的方法

如前所述,不能在类型上定义静态接口,因此无法确保强制新开发人员添加该属性

因此,你确定的两个备选方案是我能想到的唯一两个。 现在,让我们做一个正反两方面的分析,并试着把它们弄清楚

属性 您可以减轻确保开发人员将属性放在具有有意义的错误消息的类上的痛苦。我想说的是,您应该只基于属性而不是继承来管理类的发现。 如果您使用属性管理所有内容,则不需要从小部件继承。 这是一个亲,因为现在每个人都可以继承它,如果它是可取的,并重新实施,如果它的首选

缺点是可发现性的实现将更加复杂:您需要在启动时使用反射,获取
MethodInfo
,检查方法是否具有正确的签名,在情况下给出正确的错误,并根据需要调用方法取消绑定结果

想一想:您想要一个静态方法,因为您不需要实例化一个单一类型的小部件实例,但实际上实例化一个新的小部件可能不是什么大问题

抽象类 好吧,您在开发人员身上强制执行继承链,这可能是正常的、必要的或完全可选的(您判断),但您会获得一种自我记录的体验

明显的缺点是,在启动时,您需要为发现的每个派生类型实例化一个小部件,但与程序集扫描和类型检查以及methodinfo发现和通过反射进行的方法调用相比,这可能是微不足道的。 丑陋?有点效率低下?没有那么多。它是最终用户看不见的代码

依我拙见 我发现在设计框架时,在框架中放入一些“丑陋”的代码是一个很好的折衷办法,如果这意味着使用库的每个实现都会更好一点的话

总而言之,如果您要设计一个灵活且可发现的库,您应该期望开发人员至少阅读一本快速入门指南。如果他们能在5分钟内读取一点信息(“扩展一个基类”或“添加一个或多个属性”),并且这一点为他们提供了发现小部件注册的各个方面的方向,那么我就可以了:你真的没有比这更好的了

我的建议是:我会选择抽象类的路线,并提出一个小小的警告。我真的不喜欢有一个强制的基类。所以我会整理光盘