1

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

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来自用户的 a,并将其作为Detail.

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

我能想到的唯一选择是在其中嵌入一些IFoo成员子类,Detail并让 theDetail和子类相互引用。呸。

是否有防止这种类型转换的最佳实践,或者我应该将IFoo功能包含在成员子类中Detail

4

1 回答 1

3

最简单的方法是拥有一个只读包装器,它具有对可写包装器的引用。所以LessDetail总是会返回相同的包装器引用,但MoreDetail会返回对“真实”类型的引用。然后,您可以使它们都实现一个内部接口,该接口允许您做任何您需要做的事情,包装器可能会将这些调用代理到底层对象。

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

于 2012-07-09T06:25:32.677 回答