防止两个接口之间的转换

时间:2012-07-09 06:18:54

标签: c# .net interface polymorphism implementation

我有一个内部类,其中包含实现细节,包括不应公开访问的属性。我必须将这个类传递给公共调用者,并允许他们传递它,存储它,序列化它,或基本上做任何他们想要的东西。可以通过两种不同的方式公开访问该课程。这些方式作为两个公共接口公开。我想阻止用户在两个公共接口之间进行转换。这里有一些代码来演示我在说什么。

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类。

此处,用户了解IFooPlusIFoo。用户不知道Detail存在。用户也不知道LessDetail返回的对象可以转换为IFooPlus。我的代码在不同时间向用户返回相同的Detail对象,并将其返回为IFooIFooPlus,具体取决于Detail和其他内部对象的复杂状态。另请注意ProcessFoo中的ContainsDetails方法。我的代码需要能够接受用户的IFoo,并将其作为Detail进行处理。

我希望演员var more = (ContainsDetails.IFooPlus)(container.LessDetail)生成InvalidCastException。对所有IFooPlus操作进行运行时检查以确定Detail对象是否处于这些操作的正确状态是非常昂贵的。相反,我希望用户永远无法将IFoo视为IFooPlus

我能想到的唯一选择是在IFoo中嵌入一些Detail成员子类,并使Detail和子类保持彼此的引用。呸。

是否有防止此类投射的最​​佳做法,或者我应该将IFoo功能只包含在Detail的成员子类中?

1 个答案:

答案 0 :(得分:2)

最简单的方法是使用只读包装器,该包装器具有对可写入包装器的引用。因此LessDetail将始终返回相同的包装引用,但MoreDetail将返回对“real”类型的引用。然后,您可以使它们都实现一个内部接口,该接口允许您执行所需的任何操作,包装器可能代理对底层对象的调用。

或者,您可以尝试重新审视您的设计 - 目前听起来并不理想,无论是在类型之间转换还是ProcessFoo 接受编译时任何IFoo,但真的只能处理一个特定的实现。这感觉就像是对我的遗传滥用。