我理解DI背后的概念,但我只是在学习不同的IoC容器可以做什么.似乎大多数人都主张使用IoC容器来连接无状态服务,但是如何将它们用于实体等有状态对象呢?
无论是对还是错,我通常会用行为填充我的实体,即使这种行为需要外部类.例:
public class Order : IOrder
{
private string _ShipAddress;
private IShipQuoter _ShipQuoter;
public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
{
// OrderData comes from a repository and has the data needed
// to construct order
_ShipAddress = OrderData.ShipAddress; // etc.
_ShipQuoter = ShipQuoter;
}
private decimal GetShippingRate()
{
return _ShipQuoter.GetRate(this);
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,依赖项是Constructor Injected.现在提出几个问题.
让您的实体依赖于诸如ShipQuoter之类的外部类别是否被视为不良做法?如果我正确理解定义,消除这些依赖性似乎会导致我陷入贫血领域.
使用IoC容器来解决这些依赖关系并在需要时构建实体是不好的做法吗?是否有可能做到这一点?
感谢您的任何见解.
entities dependency-injection castle-windsor ioc-container inversion-of-control
采用传统的3层方法(不一定是3层):
UI BLL DAL
NHibernate如何适合?在大多数情况下,我看到人们允许NHibernate直接填充域对象/实体,这显然需要NHibernate对这些实体的引用.如果域实体是BLL的一部分,这似乎需要从DAL(NHibernate所在的位置)到BLL(域对象所在的位置)的引用.
这是否违背了分离每一层的典型思路,每层只依赖于它下面的层?我在这里错过了什么?
考虑以下表示订购系统的类:
Public Class OrderBase
Public MustOverride Property OrderItem as OrderItemBase
End Class
Public Class OrderItemBase
End Class
Run Code Online (Sandbox Code Playgroud)
现在,假设我们想要将这些类扩展为更具体的订单类集,保持OrderBase的聚合性质:
Public Class WebOrder
Inherits OrderBase
Public Overrides Property OrderItem as WebOrderItem
End Property
End Class
Public Class WebOrderItem
Inherits OrderItemBase
End Class
Run Code Online (Sandbox Code Playgroud)
WebOrder类中的Overriden属性将导致错误,指出返回类型与OrderBase中定义的类型不同...但是,返回类型是OrderBase中定义的类型的子类.为什么VB不允许这样?
创建类属性"Write Once,Read Many"的最佳方法是什么,这样您只能设置一次属性?
我知道我可以传递构造函数中的所有属性并使它们成为ReadOnly,但是在具有大量属性的情况下,我不希望构造函数具有20多个参数.
此外,我意识到我可以"滚动我自己的"设置器,但必须为每个属性执行此操作似乎是一堆冗余编码.
在VB 2008 .NET 3.5中有一个干净的方法吗?
我正在编写一个基于MVVM的VB.NET Winforms项目(使用Winforms绑定).我的直觉是永远不允许域实体处于无效状态.这要求我在构造函数中为新实体和现有实体的每个setter中进行验证检查:
Public Class Product
Public Sub New(ProductID as Integer, Name as String)
If ProductID > 0 AndAlso Name.Length > 5 Then
_ProductID = ProductID
_Name = Name
Else
Throw New InvalidProductException
End If
End Sub
Private _ProductID as Integer
Public Property ProductID as Integer
Set(value as String)
If value > 0 then
_ProductID = value
Else
Throw New InvalidProductException
End If
End Set
End Property
'Same principle as above for Name setter.
End Class
Run Code Online (Sandbox Code Playgroud)
然后我跑过Data Annotations,看起来很漂亮.我注意到大多数使用数据注释的人允许域实体暂时变为无效,然后在稍后通过调用Validate.ValidateObject来验证实体.此时,实体无效,原始状态已丢失,除非您有其他机制将其回滚.
两个问题:
1)您是否允许域名实体暂时无效?
2)根据您对#1的回答,您使用哪些技术来验证实体?
我正在开发一个基于MVVM的Winforms项目(.NET 4).为了安全起见,应用程序针对Active Directory进行身份验证,然后使用基于角色的安全性来确定对程序不同部分的访问权限.在大多数地方使用PrincipalPermissionAttribute实现安全性,如下所示:
<PrincipalPermissionAttribute(SecurityAction.Demand, Role:="Managers")> _
Public Sub Save() Implements IProductsViewModel.Save
mUOW.Commit()
End Sub
Run Code Online (Sandbox Code Playgroud)
您可以从Interface实现中了解到,此特定Sub位于ViewModel中.PrincipalPermissionAttribute正在检查当前用户(Thread.CurrentPrincipal)是否处于Manager角色.
这引出了我的问题:是否应该在域模型中完成安全检查(如上所述)?
在我自己思考时,我有两个相互矛盾的观点:
1)保持域模型不受其他许多问题的影响,以降低复杂性和依赖性.(保持安全性,可能在ViewModel中实现).
2)域模型在某种程度上是"降压停在这里"的地方.如果我在域模型中实现安全性,那么我知道即使另一层中的安全性失败,域模型也应该捕获它.
那么,你说,域模型中的安全性与否?
我有一个表,其中包含我正在编写的程序的日志条目.我正在寻找关于SQL查询的想法(我正在使用SQL Server Express 2005),它将保留最新的X数量的记录,并删除其余的.我有一个datetime列,它是日志条目的时间戳.
我认为以下内容可行,但我不确定IN子句对大量记录的性能.性能并不重要,但我也可以在第一时间做到最好.
DELETE FROM MyTable WHERE PrimaryKey NOT IN
(SELECT TOP 10,000 PrimaryKey FROM MyTable ORDER BY TimeStamp DESC)
Run Code Online (Sandbox Code Playgroud)
我应该提一下,这个查询每天运行3-4次(作为另一个进程的一部分),因此与每个查询一起删除的记录数量与将要保留的记录数量相比将会很小.
在尝试理解领域驱动设计时,我一直回到一个我似乎无法明确回答的问题.
您如何确定哪个逻辑属于Domain实体,哪些逻辑属于域服务?
示例:我们有一个在线商店的Order类.此类是实体和聚合根(它包含OrderItems).
Public Class Order:IOrder
{
Private List<IOrderItem> OrderItems
Public Order(List<IOrderItem>)
{
OrderItems = List<IOrderItem>
}
Public Decimal CalculateTotalItemWeight()
//This logic seems to belong in the entity.
{
Decimal TotalWeight = 0
foreach(IOrderItem OrderItem in OrderItems)
{
TotalWeight += OrderItem.Weight
}
return TotalWeight
}
}
Run Code Online (Sandbox Code Playgroud)
我想大多数人会同意CalculateTotalItemWeight属于实体.但是,在某些时候我们必须将此订单发送给客户.要做到这一点,我们需要做两件事:
1)确定发运此订单所需的邮资费率.
2)确定邮资费率后打印运输标签.
这两个操作都需要在Order实体之外的依赖关系,例如外部Web服务来检索邮资费率.我们该如何完成这两件事?我看到几个选项:
1)直接在域实体中编码逻辑,如CalculateTotalItemWeight.然后我们打电话:
Order.GetPostageRate
Order.PrintLabel
Run Code Online (Sandbox Code Playgroud)
2)将逻辑放在接受IOrder的服务中.然后我们打电话:
PostageService.GetPostageRate(Order)
PrintService.PrintLabel(Order)
Run Code Online (Sandbox Code Playgroud)
3)创建为对订单进行操作的每个操作的一类,并通过构造器注入传递类的订单的一个实例(这是选项1的变形,但是允许RateRetriever和LabelPrinter类的重用):
Public Class Order:IOrder
{
Private List<IOrderItem> OrderItems
Private RateRetriever _Retriever
Private LabelPrinter _Printer
Public Order(List<IOrderItem>, RateRetriever Retriever, LabelPrinter Printer)
{
OrderItems = List<IOrderItem> …
Run Code Online (Sandbox Code Playgroud) 正常使用您正在编写的 .NET 库时,会发生或多或少预期的情况。您需要通知用户/UI/调用者此事件已发生,即使它是预期的且并非异常。你:
A) 抛出异常,让UI捕获并处理。
B) 引发 UI 可以侦听的某种类型的事件。
C)做点别的事
您做了以上哪一项?如果两者都有,您对于何时抛出异常和引发事件的指导方针是什么?各自的优点和缺点是什么?
编辑:
这是我面临的一个例子。我的库使用第三方应用程序来打印运输标签,方法是启动第三方应用程序并将 XML 文件作为参数传递,该文件作为批处理类型操作进行处理。如果第三方应用程序已被用户打开,则必须先将其关闭,然后我的库才能调用它进行批处理操作。我的库检查应用程序是否正在运行,如果是,它只是停止并需要通知用户他们应该关闭第三方应用程序并重试。我完全希望这种情况发生作为图书馆正常使用的一部分。引发异常还是引发事件?
.net ×5
vb.net ×2
covariance ×1
entities ×1
entity ×1
events ×1
exception ×1
inheritance ×1
mvvm ×1
nhibernate ×1
overriding ×1
properties ×1
readonly ×1
security ×1
set ×1
sql ×1
validation ×1