0

1 つのソリューションでプロジェクト間の相互依存関係を解決しようとして苦労しています。解決策は、いくつかのプロジェクトを持つasp.netアプリケーションです。

Web プロジェクトは、SLN.Core プロジェクトの sessionwrapper クラスのサービスを使用します。次のように宣言します。

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」のようなユーザー データにアクセスできます。

モデル プロジェクトは、2 つの異なる名前空間の構造体 (モデル クラス) と DB エンジン クラスで構成されます。

上記のように、SW クラスはモデルに依存して User を宣言します。ここまでは大丈夫です。

しかし、実際には、クラスが最初に作成されたときに、デフォルト値を取得できるようにモデル オブジェクトに User、Company などのデータが必要です。F.Ex: 新しい請求書を作成する場合、ユーザー (顧客) に割り当てられた倉庫または支払タイプを取得すると便利です。

また、作業要件に従って、DB エンジンは、DB (会社ごとに 1 つ) を取得したり、ユーザー情報を含むログ エントリを保存したりするために、会社またはユーザーのデータを必要とします。

オブジェクトが DB エンジン クラスまたはメソッドへのすべての呼び出しを渡す日まで、しかし今はこれをリファクタリングしており、SW からそれぞれの場所でその情報を直接取得できれば、よりクリーンでメモリの消費が少ないと考えました。

しかし、それらの間には相互依存があります。また、SW メンバーは静的であると宣言されているため、セッションから独立して永続化できるため、インターフェイスを作成できません。

助言がありますか?

更新:以前に解決されたユーザー データの範囲に問題があったため、ここで修正しました。また、理解を深めるためにコードを追加します。ここから VB さん、申し訳ありませんが、これは多様性の優れたモデルです。

SLN.Models の 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のソリューションを取得しています。それらはプレーンなデータテーブルです。

はい、会社のデータをセッション (複数のユーザー、複数の会社がログオン) で提供するために SW で使用される Company という名前の別のモデル クラスがあります。ユーザーの構築時に、デフォルト値を SW から取得できることがわかります。たとえば、請求書の頭のような他のモデルについても同じです。それが私が望む振る舞いです。デフォルト値を取得するすべてのモデルは、New() のパラメーターとして完全なオブジェクトを取得します。一部のモデルでは、+25 flds オブジェクトから 1 つのフィールドのみが必要です。また、データのロード/クエリ/保存/削除に DBEngine を使用します。

SLN.Web では、次のようなものが表示される場合があります (ログイン):

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.tblUsersRow と SLN.DBEngine.Generic が必要です。

また、SLN.Models.tblUsers には SLN.DBEngine が必要ですが、SLN.Core.SW も取得したいと考えています ...

SLN.DBEngine... は SLN.Core.SW が必要なので、指し示す DB を知っています (その他のこと)

SLN.Web にはそれらすべてが必要です。(はぁ!)

クリア?(えっと…)

4

2 に答える 2

1

あなたの話をはっきりと理解するのは難しいです。しかし、私が得たものから、あなたのモデルはオブジェクトを作成するために current_user を必要とし (まあ、これが必要なビジネスロジックはわかりません)、web sln は current_user のモデルを必要とします。

基本的に、フローは次のようになります。

  • ユーザークラスが定義されています
  • current_user が開始されました
  • current_user を使用して、モデルは他のオブジェクトを開始します

これを達成するために利用できる方法はたくさんありますが、私は2つの解決策を提案します:

  1. この実装は、依存性注入を行うことを前提として行われます。クリーンでテスト可能。この設計は、モデル ソリューション用です。

    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
        }
    }
    
  2. この実装は、依存性注入なしで行われます。きれいではありませんが、モック可能で設計が簡単です。この設計は、モデルまたはエンティティ ソリューション用です。

    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);
        }
    }
    
于 2013-05-14T12:40:32.617 に答える
0

最終的に、SW クラスのデータ エンティティ クラスに関連するデータ エンティティ クラスを同じ CORE プロジェクトに移動することで、相互依存関係を解決しました。また、DB アクセス エンジン クラスを CORE に移動したため、モデル プロジェクトにはエンティティのみが存在し、DB アクセスを CORE に依存できます。CORE プロジェクトは何にも依存していません。すべてのエンティティが CORE 上にあり、DB アクセス エンジンも備えているからです。

最後に、悪い構造設計の別の問題でした。

また、別のシナリオでは答えが良かったので、Fendy の功績を称えたいと思います。@Fendy クレジットを与える方法を知っている場合は、教えてください。ありがとう。

于 2013-06-06T10:30:16.463 に答える