简体   繁体   English

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

[英]C# Nested Property Accessing overloading OR Sequential Operator Overloading

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. 一个获取Account对象,然后另一个获取Presence对象。 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. 这行得通,但是需要开发人员了解UserPresence类/方法,这很容易消除。

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. 我想到了一些很酷的方法来解决这个问题,并且想知道是否有人知道这些方法是否可能,是否还有其他方法可以解决这个问题,或者我们是否需要在思考过程中多考虑一些问题编码并执行UserPresence.Get而不使用属性。

  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". 如果在User类中我可以编写某种“扩展名”,说“任何时候访问User对象的Account属性的Presence对象,请执行此操作”,那将很酷。

  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 提姆

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. GetPresence方法显然也可以对User对象进行操作,而不是要求开发人员知道要传入的ID。

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. 这样一来,您可以在一次访问中将所需的所有内容加载到数据库中,并准备就绪。

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). 我只是向您展示了仅使用Account类的方式,但是您也必须使用OnlinePresence进行操作(如您所见,我假设您将拥有ProxyOnlinePresence类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM