重构以获得正确的继承/接口/协方差
本文关键字:继承 接口 方差 重构 | 更新日期: 2023-09-27 18:05:20
编辑:我已经添加了c#的相应功能,以吸引更广泛的受众-希望这是可以的
VS2008 - .Net 3.5(因此我没有得到协方差/逆变支持,据我所知?)
似乎这可能需要协方差/逆变性,因此需要。net 4,所以为了防止这个问题不可能,请随意回答。net 4,尽管如此,如果它可用,我更喜欢一个简单的重构。
这应该很简单,但由于某种原因,我的大脑今天早上就是无法应对(任何?)挑战。
我有2个应用程序(A &B).应用程序A的细节希望不重要,所以以下是WRT AppB,它有3个项目,所有类库:
- 将我的域实体暴露给AppB的其余部分,并且也暴露给AppA
- 只向AppB公开我的数据模型(使用L2S, 正常上下文和实体)
- 向AppA公开功能,使用域实体作为参数/返回类型
我在3个不同的项目中有以下接口:
Project 1 (Domain Entities)
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
}
}
如果你像这样声明你的接口会发生什么?这将需要。net 4.0+
Public Interface IAppB_Project1_Contract(Of Out TKey)
ReadOnly Property UniqueReference As TKey
End Interface
Public Interface IAppB_Project2_Contract(Of Out TKey)
Inherits IAppB_Project1_Contract(Of TKey)
End Interface
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
这会使接口的继承者与父类型共变并使代码能够运行吗?