虽然在这篇文章的评论中提到了它,但我想在此重申,您可以使用 VB.Net 创建具有嵌套类型的接口,然后在 C# 中不受限制地使用该接口及其所有嵌套类型。此外,您可以使用 ILDasm 或 ILSpy 等工具将该代码导出到 IL,然后使用 Visual Studio ILSupport 扩展将其编织回您的库中(前提是您实际上并不直接在库中需要它)。
至于有人可能想要这样做的原因,这里有两个。第一个是为一组耦合接口提供蓝图/模式定义,这些接口具有支持通用概念(例如实体管理)所需的共享泛型类型参数。例如:
public interface IEntity
<
TIEntity,
TDataObject,
TDataObjectList,
TIBusiness,
TIDataAccess,
TPrimaryKeyDataType
>
where TIEntity : IEntity<TIEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TPrimaryKeyDataType>
where TDataObject : IEntity<TIEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TPrimaryKeyDataType>.BaseDataObject
where TDataObjectList : IEntity<TIEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TPrimaryKeyDataType>.IDataObjectList
where TIBusiness : IEntity<TIEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TPrimaryKeyDataType>.IBaseBusiness
where TIDataAccess : IEntity<TIEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TPrimaryKeyDataType>.IBaseDataAccess
where TPrimaryKeyDataType : IComparable<TPrimaryKeyDataType>, IEquatable<TPrimaryKeyDataType>
{
public class BaseDataObject
{
public TPrimaryKeyDataType Id { get; set; }
}
public interface IDataObjectList : IList<TDataObject>
{
TDataObjectList ShallowClone();
}
public interface IBaseBusiness
{
void Delete(TPrimaryKeyDataType id);
TDataObjectList Load(TPrimaryKeyDataType id);
TDataObjectList Save(TDataObjectList items);
bool Validate(TDataObject item);
}
public interface IBaseDataAccess
{
void Delete(TPrimaryKeyDataType id);
TDataObjectList Load(TPrimaryKeyDataType id);
TDataObjectList Save(TDataObjectList items);
}
}
上述问题也可以通过在容器接口之外的每个嵌套接口/类上重复泛型类型参数和约束来解决,但这很快就会变得混乱。如果 .Net 支持命名空间上的泛型类型参数,另一个很好的选择,但遗憾的是目前不支持。
在接口中嵌套类型的第二个原因是提供一个组合/混合接口来定义组合接口和一个嵌套的支持作曲家类,提供接受混合实例的功能以构造一个新的动态类,该类实现组合接口并将调用转发到混合。如下所示:
public interface IComposite<TIComposite, TIMixin1, TIMixin2>
where TIComposite : class, IComposite<TIComposite, TIMixin1, TIMixin2>, TIMixin1, TIMixin2
where TIMixin1 : class
where TIMixin2 : class
{
public class Composer
{
public static TIComposite Create(TIMixin1 mixin1, TIMixin2 mixin2)
{
...
}
}
}
然后,您可以创建扩展上述 IComposite 接口的接口,该接口已经包含扩展接口的适当编写器。请注意,您还可能拥有 IComposite 接口的其他变体来支持更多数量的 mixin(类似于 Func 和 Action,因为 .Net 目前不支持可变泛型类型参数)。
您可以像在以下示例中一样使用它:
public interface IPerson
{
string FirstName;
string LastName;
}
public interface ILock
{
object GetLock();
}
public interface ILockablePerson : IComposite<ILockablePerson, IPerson, ILockable>, IPerson, ILockable {}
public class Person : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Lock : ILock
{
private
readonly object lock = new object();
public object GetLock() { return this.lock; }
}
public class UseLockablePerson
{
public void Main()
{
var lockablePerson = ILockablePerson.Composer.Create(new Person(), new Lock());
lock(lockablePerson.GetLock())
{
lockablePerson.FirstName = "Bob";
}
}
}
虽然可以在 IComposite 接口之外创建 Composer 类,但发现其组合支持或意图并不像在 IntelliSense 中看到 Composer 那样容易。在这种情况下,嵌套的 Composer 类实际上用于为接口提供静态方法 (Create)(这是另一个不受支持的选项)。