0

嘿,我一直在寻找解决我们在代码库中遇到的棘手问题的方法。

首先,我们的代码类似于以下内容:

class User
{ 
   int id;
   int accountId;

   Account account
   {
     get { return Account.Get(accountId); }
   }     
}

class Account
{
   int accountId;
   OnlinePresence Presence
   {
      get { return OnlinePresence.Get(accountId); }  
   } 
   public static Account Get(int accountId)
   {
      // hits a database and gets back our object.
   }
}

class OnlinePresence
{
   int accountId;
   bool isOnline;
   public static OnlinePresence Get(int accountId)
   {
      // hits a database and gets back our object.
   }
}

我们在代码中经常做的是尝试通过以下方式访问用户的帐户存在

var presence = user.Account.Presence;

问题在于这实际上是向数据库发出两个请求。一个获取 Account 对象,然后一个获取 Presence 对象。如果我们执行以下操作,我们可以轻松地将其归结为一个请求:

var presence = UserPresence.Get(user.id);

这可行,但有点要求开发人员了解 UserPresence 类/方法,这样可以很好地消除。

我已经想到了一些很酷的方法来解决这个问题,并且想知道是否有人知道这些是否可能,是否有其他方法来处理这个问题,或者我们是否需要更多地思考编码并执行 UserPresence.Get 而不是使用属性。

  1. 重载嵌套访问器。如果在 User 类中我可以编写某种“扩展”,它会说“任何时候访问 User 对象的 Account 属性的 Presence 对象,就这样做会很酷”。

  2. 重载 . 操作员知道接下来会发生什么。如果我能以某种方式使 . 运算符仅在右侧的对象也被“点缀”的情况下会很棒。

这两件事似乎都可以在编译时处理,但也许我遗漏了一些东西(反射会让这变得困难吗?)。我是否完全错误地看待事物?有没有一种方法可以消除业务逻辑用户的负担?

谢谢!蒂姆

4

2 回答 2

0

认为代理模式更好。

class User
{
    int id;
    int accountId;

    Account Account
    {
        get { return new ProxyAccount(accountId); }
    }
}

abstract class Account
{
    protected int accountId;

    protected Account(int accountId)
    {
        this.accountId = accountId;
    }

    public OnlinePresence Presence
    {
       get { return new ProxyOnlinePresence(accountId); }
    }

    /*
        other properties of the Account go here as abstract properties

        public abstract string SomeProperty { get; set; }

    */

    public static Account Get(int accountId)
    {
        // hits a database and returns an instance of DBAccount.
    }
}

class ProxyAccount : Account
{
    private Account account;
    public ProxyAccount(int accountId) : base(accountId)
    {
    }

    private Account GetAccount()
    {
        if (account == null)
            account = Account.Get(accountId);
        return account;
    }

    /*
        Accounts abstract properties are implemented here

        public override string SomeProperty
        {
            get { return GetAccount().SomeProperty; }
            set { GetAccount().SomeProperty = value; }
        }
    */
}

class DBAccount : Account
{
    public DBAccount(int accountId) : base(accountId)
    {
    }

    /*
        Accounts abstract properties are implemented here

        public override string SomeProperty { get; set; }
    */
}

我只是向您展示了仅使用 Account 类的方法,但您还必须使用 OnlinePresence 来完成(如您所见,我假设您将拥有一个 ProxyOnlinePresence 类)。

于 2010-04-15T18:41:03.947 回答
0

为什么不使用存储库模式并具有以下内容:

public class UserPresenceRepository
{
    public UserPresenceRepository(string connString)
    {
        // configure db properties
    }

    public UserPresence GetPresence(User user)
    {
        // get precense from user.accountId if possible 
        // and skip the trip for Account
    }
}

所以你的调用代码看起来像:

UserPresenceRepository repo = new UserPresenceRepository(connString);
repo.GetPresence(user);

如果您需要用户存在信息,最终结果是明确定义要调用的存储库。该GetPresence方法还清楚地对User对象进行了操作,而不是要求开发人员知道要传入哪个 Id。

这里的另一个选项是停止延迟加载您的对象。这样,您可以一次将所需的所有内容加载到数据库并准备好。

于 2010-04-15T18:02:06.130 回答