是否可以将基数 class 限制为特定子 class?
Is it possible to restrict a base class to a specific subclass?
我有一个需要,我希望有一个基地 class 只对一个特定的子 class 可用。这是由于无法将 Attribute
定义为泛型的内部 class 的限制。
我们想要在泛型中定义属性的原因是当您这样做并将其类型设置为 protected
时,该属性现在仅可用于您的基础 classes class,保持您的 API 清洁。
例如,考虑继承自 MarkupExtension
的抽象 class ExampleMarkupExtension<T>
。我想将属性 StaticInfoAttribute
定义为内部 class,因此它仅适用于 ExampleMarkupExtension<T>
.
的子class
但是,如前所述,您不能将属性定义为泛型的内部 class,因此我的解决方法是创建第二个非泛型 ExampleMarkupExtensionBase
class 继承自 MarkupExtension
,将 StaticInfoAttribute
定义为内部 class,然后让泛型继承自 class。
现在的问题是我的层次结构中有一个额外的 class,任何人都可以子class。虽然它在技术上是无害的,但我喜欢保持我的 API 表面积清洁。
例子
ExampleMarkupExtensionBase
: 非通用抽象基础 class
这是定义属性的 class,该属性应该仅供此 class 的子class使用。这个 class 之所以存在,是因为我不能将 StaticInfoAttribute
放在下面的通用抽象基础 class ExampleMarkupExtension<T>
中。
public abstract class ExampleMarkupExtensionBase : MarkupExtension {
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
protected class StaticInfoAttribute : Attribute {
public StaticInfoAttribute(string value) => Value = value;
public readonly string Value;
}
}
ExampleMarkupExtension<T>
: 通用抽象基础 class
这是 class,它包含此 class 的子 class 所独有的静态成员。它通过使用 subclass 作为基础 class 的类型参数来实现这一点(参见 where
子句)。静态字段的值是根据属性设置的,因此它仅对上面 ExampleMarkupExtension
的这个特定子 class 有用。
public abstract class ExampleMarkupExtension<T> : ExampleMarkupExtensionBase
where T : ExampleMarkupExtension<T> {
static ExampleMarkupExtension() => Value = typeof(T).GetRequiredCustomAttribute<StaticInfoAttribute>().Value;
public static readonly string Value;
public sealed override object ProvideValue(IServiceProvider serviceProvider)
=> Value;
}
理由
有些人可能会问保持原样有什么坏处。从技术上讲,让一个人subclassExampleMarkupExtensionBase
并没有错。只是没有意义。
就此而言,从技术上讲,将 StaticInfoAttribute
移到 class 之外也没有任何危害,完全消除了对非通用基 class 的需要。我只是选择了前一种方法,因为限制属性的使用比阻止某人从 subclassing 基础 class.
更重要
根据我们的评论,您可以使用 EditorBrowsable
属性从引用它的项目中隐藏该方法。但是请注意,它只是对 IntelliSense 隐藏了它,如果用户输入 ExampleMarkupExtensionBase
,则 class 仍然存在并且可以使用。
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class ExampleMarkupExtensionBase : MarkupExtension
我有一个需要,我希望有一个基地 class 只对一个特定的子 class 可用。这是由于无法将 Attribute
定义为泛型的内部 class 的限制。
我们想要在泛型中定义属性的原因是当您这样做并将其类型设置为 protected
时,该属性现在仅可用于您的基础 classes class,保持您的 API 清洁。
例如,考虑继承自 MarkupExtension
的抽象 class ExampleMarkupExtension<T>
。我想将属性 StaticInfoAttribute
定义为内部 class,因此它仅适用于 ExampleMarkupExtension<T>
.
但是,如前所述,您不能将属性定义为泛型的内部 class,因此我的解决方法是创建第二个非泛型 ExampleMarkupExtensionBase
class 继承自 MarkupExtension
,将 StaticInfoAttribute
定义为内部 class,然后让泛型继承自 class。
现在的问题是我的层次结构中有一个额外的 class,任何人都可以子class。虽然它在技术上是无害的,但我喜欢保持我的 API 表面积清洁。
例子
ExampleMarkupExtensionBase
: 非通用抽象基础 class
这是定义属性的 class,该属性应该仅供此 class 的子class使用。这个 class 之所以存在,是因为我不能将 StaticInfoAttribute
放在下面的通用抽象基础 class ExampleMarkupExtension<T>
中。
public abstract class ExampleMarkupExtensionBase : MarkupExtension {
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
protected class StaticInfoAttribute : Attribute {
public StaticInfoAttribute(string value) => Value = value;
public readonly string Value;
}
}
ExampleMarkupExtension<T>
: 通用抽象基础 class
这是 class,它包含此 class 的子 class 所独有的静态成员。它通过使用 subclass 作为基础 class 的类型参数来实现这一点(参见 where
子句)。静态字段的值是根据属性设置的,因此它仅对上面 ExampleMarkupExtension
的这个特定子 class 有用。
public abstract class ExampleMarkupExtension<T> : ExampleMarkupExtensionBase
where T : ExampleMarkupExtension<T> {
static ExampleMarkupExtension() => Value = typeof(T).GetRequiredCustomAttribute<StaticInfoAttribute>().Value;
public static readonly string Value;
public sealed override object ProvideValue(IServiceProvider serviceProvider)
=> Value;
}
理由
有些人可能会问保持原样有什么坏处。从技术上讲,让一个人subclassExampleMarkupExtensionBase
并没有错。只是没有意义。
就此而言,从技术上讲,将 StaticInfoAttribute
移到 class 之外也没有任何危害,完全消除了对非通用基 class 的需要。我只是选择了前一种方法,因为限制属性的使用比阻止某人从 subclassing 基础 class.
根据我们的评论,您可以使用 EditorBrowsable
属性从引用它的项目中隐藏该方法。但是请注意,它只是对 IntelliSense 隐藏了它,如果用户输入 ExampleMarkupExtensionBase
,则 class 仍然存在并且可以使用。
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class ExampleMarkupExtensionBase : MarkupExtension