【发布时间】:2011-10-23 21:51:52
【问题描述】:
编辑:我添加了 C# 等效项以吸引更广泛的受众 - 希望没关系
VS2008 - .Net 3.5(据我所知,我没有获得协变/逆变支持?)
似乎这可能需要协变/逆变,因此需要 .Net 4,所以为了防止这个问题是不可能的,尽管请随意回答 .Net4,如果它可用的话,我更喜欢简单的重构。
这应该很简单,但由于某种原因,我的大脑无法应对今天早上的(任何?)挑战。
我有 2 个应用程序(A 和 B)。应用程序 A 的详细信息希望并不重要,因此以下是 WRT AppB,它有 3 个项目,所有类库:
- 将我的域实体暴露给 AppB 的其余部分,同时也暴露给 AppA
- 仅将我的数据模型公开给 AppB(使用 L2S、正常上下文和实体)
- 向 AppA 公开功能,使用域实体作为参数/返回类型
我在 3 个不同的项目中有以下接口:
在项目 1(域实体)中
VB:
Public Interface IAppB_Project1_Contract(Of TKey)
ReadOnly Property UniqueReference As TKey
End Interface
C#
public interface IAppB_Project1_Contract<TKey>
{
TKey UniqueReference { get; }
}
在项目 2(数据模型)中
VB:
Public Interface IAppB_Project2_Contract(Of TKey)
Inherits IAppB_Project1_Contract(Of TKey)
End Interface
C#:
public interface IAppB_Project2_Contract<TKey> : IAppB_Project1_Contract<TKey>
{
}
在项目 3(功能)中
VB:
Public Interface IAppB_Project3_Contract
Function Create(Of T As {Class, IAppB_Project1_Contract(Of TKey)}, TKey)(ByVal entity As T) As TKey
End Interface
C#:
public interface IAppB_Project3_Contract
{
TKey Create<T, TKey>(T entity) where T : class, IAppB_Project1_Contract<TKey>;
}
这个想法是,功能合同(在项目 3 中)将仅使用域实体(在项目 1 中)作为参数/返回,因为只有项目 1 和 3 暴露给应用程序 A,而项目 2 没有。
我的 L2S 实体已扩展为实现 Project 2 接口。实际上,项目 2 的合同中还有其他几种方法,但希望不相关。
直到我真正输入它之前,出于某种原因,我一直认为我会通过以下项目 3 合同的实现来逃脱:
VB:
Public Class Project3_Implementation
Implements IAppB_Project3_Contract
Public Function Create(Of T As {Class, IApp_Project2_Contract(Of TKey)}, TKey)(ByVal entity As T) As TKey Implements IAppB_Project3_Contract.Create
' notice the very subtle change to *Project TWO's* contract in the generics' constraint
End Function
End Class
C#:
public class Project3_Implementation : IAppB_Project3_Contract
{
public TKey Create<T, TKey>(T entity) where T : class, IApp_Project2_Contract<TKey>
{
// notice the very subtle change to *Project TWO's* contract in the generics' constraint
}
}
这在我脑海中工作了一段时间,因为项目 2 的合同继承了项目 1 的合同,但当然不是这样,因为我已经缩小约束,因此无法实现相应的项目 3 接口。
问题是,我将如何实现我所追求的目标:
- 项目 2 应该对应用程序 A 保持不可见,但项目 1 和 3 是公开的,并且应该描述可用的功能以及应用程序 A 可以/必须使用哪些实体才能调用应用程序 B
- 理想情况下,项目 3 合同的实施将参数限制为实际上是隐藏项目 2 中声明的实体。
我有一种感觉,我在问不可能的事情,但我希望有人能跳出框框来提出一些建议,我可以改变以实现或接近实现我的目标?
提前致谢!!
编辑:
我知道这个问题并不清楚,因为我在问题中描述的只是如何做错事...
这里有更多关于项目 3 合同实施的详细信息,希望能让事情更清楚(请记住项目 2 的合同仅由自动生成的 Linq 实体实施):
VB:
Public Class MyImplementation
Inherits System.Data.Linq.DataContext
Implements IAppB_Project3_Contract
Public Function Create(Of T As {Class, IApp_Project2_Contract(Of TKey)}, TKey)(ByVal entity As T) As TKey Implements IAppB_Project3_Contract.Create
Me.GetTable(Of T).InsertOnSubmit(entity)
Return entity.UniqueReference ' the entity will implement the IApp_Project2_Contract by exposings it primary key - Return Me.MyPrimaryKeyField
End Function
End Class
C#:
public class MyImplementation : System.Data.Linq.DataContext, IAppB_Project3_Contract
{
public TKey Create<T, TKey>(T entity) where T : class, IApp_Project2_Contract<TKey>
{
this.GetTable<T>.InsertOnSubmit(entity);
return entity.UniqueReference;
// the entity will implement the IApp_Project2_Contract by exposings it primary key - Return Me.MyPrimaryKeyField
}
}
【问题讨论】:
-
为什么要为每个项目添加限制?我根本不明白为什么你需要定义这样的键?钥匙只是您的解决方案,我想知道您要解决的原始问题。如果我不了解实际问题,则无法正确回答。
-
我知道这个问题有点混乱,请随时提出清理它的方法并使其更清晰。干杯!
-
@jguaffin - 不确定你指的是哪一部分?项目限制?我不希望应用程序 A 通过项目 2 的上下文直接联系数据库,数据非常敏感,需要通过项目 3 进行大量验证、转换等。关于键,我不能重载类 - 有时是表/entity 键是整数,有时是 Short,有时是 Long,有时是 GUID,等等……所以我使用了泛型和合同。我将添加一个快速的 sn-p 以显示我在 Project 3 实施中尝试做的事情...
-
这不是一个协变/逆变问题吗?
-
不要暴露数据库或数据库对象。添加一个执行所有验证的公共域层。限制数据库,以便只有正确的项目可以访问它(使用它自己的凭据)
标签: c# vb.net inheritance interface