如何解决交叉依赖
本文关键字:依赖 解决 何解决 | 更新日期: 2023-09-27 18:13:21
我很难在一个解决方案中解决项目之间的交叉依赖。解决方案是一个包含多个项目的asp.net应用程序。
web项目使用SLN中会话包装器类的服务。核心项目。声明:
public sealed class SW
{
public static tblUserRow User
{
get
{
if (HttpContext.Current == null) return null;
return HttpContext.Current.Session["dtUser"] == null ? null : (tblUsersRow)(HttpContext.Current.Session["dtUser"] as tblUsers).Rows[0];
}
}
public static void User_Load(string userId)
{
tblUsers users = new tblUsers();
users.LoadByID(userId);
if (users.Count != 0)
{
HttpContext.Current.Session["dtUser"] = users;
}
}
}
tblUserRow是独立模型项目中用户类(强类型数据表)的模型定义的一部分。在SW类中还有其他一些方法,但不相关。在SLN中。Web我可以访问用户数据,如"SW.User.Name"
模型项目由两个不同命名空间中的结构(模型类)和DB引擎类组成。
如上面所见,SW类依赖于要声明User的模型。到这里为止,一切正常。但事实是,模型对象在第一次创建类时需要User、Company等数据,以便它们可以获得默认值。联邦快递:如果你创建一个新的发票,最好能得到用户(客户)指定的仓库或付款类型。
根据工作需求,DB引擎需要公司或用户数据来完成诸如获取DB(每个公司一个)或保存带有用户信息的日志条目之类的事情。
直到对象在每次调用DB引擎类甚至方法时传递的那一天,但现在我正在重构这个,我认为如果可以直接从SW的相应位置获得该信息将更干净,内存消耗更少。
但它们之间存在交叉依赖关系。由于SW成员被声明为静态,因此它们可以独立于会话进行持久化,因此我无法创建接口。
有什么建议吗?
UPDATE:用户数据的范围有一个问题,以前已经解决了,所以我在这里更正。此外,我将添加一些更多的代码,以便更好地理解。从这里VB,抱歉伙计们,但这是一个很好的多样性模型。
SLN中tblUser模型的示例。模型:
<DesignerCategory("Code"), System.SerializableAttribute()>
Partial Public Class tblUsers
Inherits TypedTableBase(Of tblUsersRow)
<DebuggerNonUserCodeAttribute()>
Public Sub New()
MyBase.New()
BeginInit()
InitClass()
EndInit()
End Sub
<DebuggerNonUserCodeAttribute()>
Private Sub InitClass()
TableName = TABLE_NAME
With Columns
.Add(New DataColumn(FIELD_ID, GetType(String)))
.Add(New DataColumn(FIELD_Name, GetType(String)))
...
'Added that last columns as example
.Add(New DataColumn(FIELD_Company, GetType(String)) With {.DefaultValue=SW.Company.ID})
.Add(New DataColumn(FIELD_Warehouse, GetType(String)) With {.DefaultValue=SW.Company.Warehouse})
End With
Dim keys(1) As DataColumn
keys(0) = Columns(0)
PrimaryKey = keys
End Sub
...
<DebuggerNonUserCodeAttribute()>
Public Sub LoadByID(Id As String)
Rows.Clear()
Merge(New SLN.DBEngine.Generic(SW.Company.Connection, doLog:=False).ExecuteQuery(COMMAND_LOADBY_ID, Id))
End Sub
...
End Class
Partial Public Class tblUsersRow
Inherits DataRow
<DebuggerNonUserCodeAttribute()>
Friend Sub New(ByVal builder As DataRowBuilder)
MyBase.New(builder)
End Sub
<DebuggerNonUserCodeAttribute()>
Public Property ID() As String
Get
Return DirectCast(MyBase.Item(0), String)
End Get
Set(value As String)
MyBase.Item(0) = value
End Set
End Property
<DebuggerNonUserCodeAttribute()>
Public Property Name() As String
Get
Return DirectCast(MyBase.Item(1), String)
End Get
Set(value As String)
MyBase.Item(1) = value
End Set
End Property
...
End Class
**模型类是这样的,而我得到EF多个DB的解决方案。它们是纯数据表。
是的,还有另一个名为Company的模型类,它也用于在SW中提供会话中的公司数据(多个用户,多个公司登录)您可以看到,在用户构造中,可以从软件中检索缺省值。其他模型也一样,例如发票头。这就是我想要的行为。到目前为止,所有获得默认值的模型都将获得一个完整的对象作为New()的参数。有些模型只需要+25个flds对象中的一个字段。他们还使用DBEngine来加载/查询/保存/删除数据。
在SLN。Web上可能会看到这样的内容(login):
SW.Company_Load(ddlCompany.Text)
sDescription = New Generic(SW.Company.Connection,False).ExecuteQuery("sp_Warehouse_LoadBy_Id",SW.User.Warehouse).Rows(0)("rDescription").ToString
这是个粗略的例子。
所以SLN.Core.SW需要sln . models . tbluserrow和SLN.DBEngine.Generic
和SLN. models . tblusers需要SLN。但也想获得SLN.Core.SW…
SLN.DBEngine……需要SLN.Core.SW,所以他知道DB指向(一些其他的东西)
和SLN。Web需要所有这些。(叹息)
清楚了吗?(哦…)
很难清楚地理解你的故事。但是从我得到的,你的模型需要current_user来创建对象(好吧,我不明白为什么需要这个业务逻辑),你的web需要current_user的模型。
基本上,流程应该是这样的:
- 用户类已定义
- current_user被启动 使用current_user,模型将初始化其他对象
有很多方法可以做到这一点,但我提出两个解决方案:
-
这个实现是在你做依赖注入的情况下完成的。干净,可测试。本设计为模型解决方案。
public interface IUserProvider { User CurrentUser { get; } } public class ModelCreator { public ModelCreator(IUserProvider provider) { this.provider = provider; } IUserProvider provider; public Invoice Get(){ User currentUser = provider.CurrentUser; // do other } }
-
这个实现是不需要依赖注入的。不干净,但嘲弄和易于设计。本设计适用于模型或实体解决方案。
public static class UserProvider { private static Func<User> currentUserDelegate = new Func<User>(NullUser); public static Func<User> CurrentUserDelegate { set { currentUserDelegate = value; } } private static User NullUser() { return null; } public static User CurrentUser { get { return currentUserDelegate(); } } }
用法:
public sealed class SW { private static User _currentUser; public static User GetCurrentUser() { if (_currentUser == null) { tblUsers users = new tblUsers(); users.LoadByID(userId); HttpContext.Current.Session["dtUser"] = users; _currentUser = users[0]; } return _currentUser; } public static void User_Load(string userId) { UserProvider.CurrentUserDelegate = new Func<User>(GetCurrentUser); } }
我最终通过将与SW类相关的数据实体类移动到同一个CORE项目中来解决交叉依赖。还将数据库访问引擎类移动到CORE,因此在模型项目中只有实体,它可以依赖于CORE进行数据库访问。CORE项目不依赖于任何东西,因为它的所有实体都在它上面,也有DB访问引擎。
所以最后的问题是糟糕的基础设施设计。
我也想把功劳给Fendy,因为在其他情况下答案是好的。@Fendy如果你知道什么方法可以给你加分,请告诉我。谢谢。