C# 嵌套属性访问重载或顺序运算符重载

发布于 2024-08-29 17:25:05 字数 1350 浏览 3 评论 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. 超载 .操作员知道接下来会发生什么。 如果我能以某种方式使 .运算符仅在右侧对象也被“点缀”的情况下使用,那就太好了。

这两件事看起来都可以在编译时处理,但也许我遗漏了一些东西(反射会让这变得困难吗?)。我看待事物的方式完全错误吗?有没有一种方法可以强制执行此操作,从而减轻业务逻辑用户的负担?

谢谢! 蒂姆

Hey, I've been searching around for a solution to a tricky problem we're having with our code base.

To start, our code resembles the following:

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.
   }
}

What we're often doing in our code is trying to access the account Presence of a user by doing

var presence = user.Account.Presence;

The problem with this is that this is actually making two requests to the database. One to get the Account object, and then one to get the Presence object. We could easily knock this down to one request if we did the following :

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

This works, but sort of requires developers to have an understanding of the UserPresence class/methods that would be nice to eliminate.

I've thought of a couple of cool ways to be able to handle this problem, and was wondering if anyone knows if these are possible, if there are other ways of handling this, or if we just need to think more as we're coding and do the UserPresence.Get instead of using properties.

  1. Overload nested accessors.
    It would be cool if inside the User class I could write some sort of "extension" that would say "any time a User object's Account property's Presence object is being accessed, do this instead".

  2. Overload the . operator with knowledge of what comes after.
    If I could somehow overload the . operator only in situations where the object on the right is also being "dotted" it would be great.

Both of these seem like things that could be handled at compile time, but perhaps I'm missing something (would reflection make this difficult?). Am I looking at things completely incorrectly? Is there a way of enforcing this that removes the burden from the user of the business logic?

Thanks!
Tim

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2024-09-05 17:25:05

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

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。

此处的另一个选项是停止延迟加载对象。这样您就可以一次性加载所需的所有内容到数据库并准备就绪。

Why not go with the Repository pattern and have the following:

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
    }
}

So your calling code would look like:

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

The end result is a clear definition of a Repository to call if you need User Presence information. The GetPresence method also clearly operates on the User object instead of requiring developers to know which Id to pass in.

The other option here would to stop lazy loading your objects. That way you can load everything you need in one trip to the database and have it ready.

西瑶 2024-09-05 17:25:05

认为代理模式更好。

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 类)。

Think it's better the Proxy pattern.

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; }
    */
}

I just showed you the way only with Account class, but you also have to do it with OnlinePresence as well (as you can see, I've assumed you'll have a ProxyOnlinePresence class).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文