C# 防止在两个接口之间强制转换

C# 防止在两个接口之间强制转换,c#,.net,interface,polymorphism,implementation,C#,.net,Interface,Polymorphism,Implementation,我有一个内部类,它包含实现细节,包括属性,不应该公开访问。我必须将这个类传递给公共调用方,并允许他们传递、存储、序列化它,或者基本上用它做任何他们想做的事情。该类可以通过两种不同的方式公开访问。这些方法公开为两个公共接口。我想防止用户在两个公共接口之间强制转换。下面是一些代码来演示我所说的内容 void Main() { var container = new ContainsDetails(5); Console.WriteLine(container.LessDetail.

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

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
的角色。类似地,
Detail
在我的实际代码中是一个
internal

在这里,用户了解
IFooPlus
IFoo
。用户不知道存在
详细信息
。用户也不知道
LessDetail
返回的对象是否可转换为
IFooPlus
。我的代码在不同的时间向用户返回相同的
Detail
对象,并根据
Detail
和其他内部对象的复杂状态,将其作为
IFoo
IFooPlus
返回。还要注意
中的
ProcessFoo
方法包含详细信息。我的代码需要能够接受来自用户的
IFoo
,并将其作为
详细信息处理

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

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


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

最简单的方法是使用一个只读包装器,其中引用了可写的包装器。因此
LessDetail
将始终返回相同的包装器引用,但是
moredeail
将返回对“real”类型的引用。然后,您可以让它们都实现一个内部接口,该接口允许您做任何需要做的事情,包装器可能会将这些调用代理给底层对象


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

事实上,IFoo是IAsyncResult,ProcessFoo是BeginReadxxx、EndRead、BeginWritexxx等。我不能接受比IFoo(IAsyncResult)更严格的限制,因为我的代码需要符合旧的异步模式。@MichaelGraczyk:这很难看,但至少是一个合理的解释。这就是为什么在这个问题中提供上下文是值得的…是的,我希望有一些创造性的方法来覆盖casting操作符,只抛出一个异常
IFoo
IFooPlus
与线程同步代码紧密耦合。在用户的回调中,我必须小心不要更改状态:)。如果这样的强制转换覆盖不存在,我将尝试使用只读包装类。谢谢