我有一个内部类,其中包含实现细节,包括不应公开访问的属性。我必须将这个类传递给公共调用者,并允许他们传递它,存储它,序列化它,或基本上做任何他们想要的东西。可以通过两种不同的方式公开访问该课程。这些方式作为两个公共接口公开。我想阻止用户在两个公共接口之间进行转换。这里有一些代码来演示我在说什么。
void Main()
{
var container = new ContainsDetails(5);
Console.WriteLine(container.LessDetail.TheDetails);
var more = (ContainsDetails.IFooPlus)(container.LessDetail);
more.TheDetails = 10;
Console.WriteLine(container.LessDetail.TheDetails);
}
public class ContainsDetails {
public interface IFooPlus {
int TheDetails {
get;
set;
}
}
public interface IFoo {
int TheDetails {
get;
}
}
private readonly Detail _myDetail;
public ContainsDetails(int x) {
_myDetail = new Detail(x);
}
public IFoo LessDetail {
get {
return _myDetail;
}
}
public IFooPlus MoreDetail {
get {
return _myDetail;
}
}
public bool ProcessFoo(IFoo foo) {
var theDeets = foo as Detail;
if (theDeets != null) {
return theDeets.TheDetails++%2 == 0;
} else {
throw new ArgumentException("foo argument must have originated from ContainsDetails.");
}
}
private class Detail : IFooPlus, IFoo {
private int _myX;
private Detail() {}
internal Detail(int x) {
_myX = x;
}
public int TheDetails {
get {return _myX; }
set { _myX = value; }
}
}
}
输出是:
5
10
我想上面的输出是:
5
System.InvalidCastException thrown.....
班级ContainsDetails
仅用于演示。在我的实际代码中,程序集填充ContainsDetails
的角色。同样,Detail
在我的实际代码中是internal
类。
此处,用户了解IFooPlus
和IFoo
。用户不知道Detail
存在。用户也不知道LessDetail
返回的对象可以转换为IFooPlus
。我的代码在不同时间向用户返回相同的Detail
对象,并将其返回为IFoo
或IFooPlus
,具体取决于Detail
和其他内部对象的复杂状态。另请注意ProcessFoo
中的ContainsDetails
方法。我的代码需要能够接受用户的IFoo
,并将其作为Detail
进行处理。
我希望演员var more = (ContainsDetails.IFooPlus)(container.LessDetail)
生成InvalidCastException
。对所有IFooPlus
操作进行运行时检查以确定Detail
对象是否处于这些操作的正确状态是非常昂贵的。相反,我希望用户永远无法将IFoo
视为IFooPlus
。
我能想到的唯一选择是在IFoo
中嵌入一些Detail
成员子类,并使Detail
和子类保持彼此的引用。呸。
是否有防止此类投射的最佳做法,或者我应该将IFoo
功能只包含在Detail
的成员子类中?
答案 0 :(得分:2)
最简单的方法是使用只读包装器,该包装器具有对可写入包装器的引用。因此LessDetail
将始终返回相同的包装引用,但MoreDetail
将返回对“real”类型的引用。然后,您可以使它们都实现一个内部接口,该接口允许您执行所需的任何操作,包装器可能代理对底层对象的调用。
或者,您可以尝试重新审视您的设计 - 目前听起来并不理想,无论是在类型之间转换还是ProcessFoo
接受编译时任何IFoo
,但真的只能处理一个特定的实现。这感觉就像是对我的遗传滥用。