我们说我有一个经理类
public class Manager {
public Item Create() {
...
return new Item(...);
}
}
我有一个Item类:
public class Item {
[AllowCallBy(typeof(Manager))]
public Item(...) {
}
...
}
现在,我想使用最简单,最直接的方法在编译时分析AllowCallBy
等属性并显示错误或警告。如果在这种特殊情况下,Manager类以外的类尝试使用Item
实例化new Item(...)
,我想显示类似于"不要直接实例化Item类,调用Manager 。而不是创建(...)"。
我认为至少有一个系统:Roslyn,ReSharper,PostSharp或者别的东西可以让我这样做,或者与我想要达到的非常接近的东西。有人可以举例说明使用什么以及如何使用它吗?
答案 0 :(得分:3)
@Habib提到这肯定是code smell(有人可以链接到特定的吗?),但如果没有更完整的例子,除了评论中已经提出的建议之外,很难提供替代方案。我鼓励您扩展样本或重新考虑您的设计。
但是,我可以提供过去曾用过的一个选项,但不是为了这个目的。您可以将Item
的构造函数标记为Obsolete
:
public class Item {
[Obsolete("Don't instantiate Item class directly, call Manager.Create(...) instead")]
public Item(...) {
}
...
}
然后在你的Manager
课程中,你在调用构造函数时特别忽略了这个警告:
public class Manager {
public Item Create() {
...
#pragma warning disable 618
return new Item(...);
#pragma warning restore 618
}
}
这样,每当有人尝试在代码中的其他地方创建自己的Item
时,他们就会得到level 2 CS0618 warning,表明他们不应使用该方法(请注意,我并没有说不能),而且确切地说是在属性中输入的文本。如果启用了warnings as errors(对于所有警告或只是这个警告),那么它将是您最初想要的编译错误。
请注意,没有什么能阻止他人添加这些pragma
语句来解决错误。但是,使用这种方法,开发人员不能说他们并不知道他们不应该使用构造函数。
答案 1 :(得分:1)
ComponentInternalAttribute
来控制类型的可见性:
public class Item {
[ComponentInternal(typeof(Manager))]
public Item(...) {
}
...
}
根据上面链接的文档,尝试在Item
之外调用Manager
的构造函数将产生编译时警告:
由于[ComponentInternal]约束,无法从 [其他方法] 引用方法Item.ctor。
您可以通过更改属性的严重性级别来使其成为错误:
public class Item {
[ComponentInternal(typeof(Manager), Severity = SeverityType.Error)]
public Item(...) {
}
...
}
答案 2 :(得分:0)
有更好的方法来实现您的目标,而不是您当前的方法,,因为您可以实际更改该代码。
例如,您可以将Item类的构造标记为private,并向Item类添加一个静态工厂方法,该类负责创建该类的实例。
另一种方法是将Item类移动到另一个程序集,将其构造函数标记为internal,并实现另一个类(工厂),该类负责创建不同的Item对象。然后,您可以从其他程序集中看到该类,但它无法直接实例化,因此强制代码用户使用提供的工厂。