Вложенное свойство C # Доступ к перегрузке ИЛИ последовательная перегрузка оператора - PullRequest
0 голосов
/ 15 апреля 2010

Эй, я искал решение сложной проблемы, которую мы имеем с нашей кодовой базой.

Для начала наш код напоминает следующее:

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 я мог бы написать какое-то «расширение», которое бы сообщало: «каждый раз, когда к объекту Presence объекта User присваивается доступ, используйте это вместо этого».

  2. Перегрузка. оператор со знанием того, что будет после. Если бы я мог как-то перегрузить. Оператор только в ситуациях, когда объект справа также «пунктирный», было бы здорово.

Обе эти вещи кажутся вещами, которые могут быть обработаны во время компиляции, но, возможно, я что-то упускаю (размышление затруднит это?). Я смотрю на вещи совершенно неправильно? Есть ли способ применить это, чтобы снять нагрузку с пользователя на бизнес-логику?

Спасибо! Тим

Ответы [ 2 ]

0 голосов
/ 15 апреля 2010

Подумайте, лучше шаблон Proxy.

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

0 голосов
/ 15 апреля 2010

Почему бы не пойти с шаблоном Repository и иметь следующее:

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, вместо того, чтобы требовать от разработчиков знать, какой идентификатор передать.

Другой вариант - прекратить ленивую загрузку ваших объектов. Таким образом, вы можете загрузить все, что вам нужно, за одну поездку в базу данных и подготовить ее.

...