Преобразование существующего экземпляра класса в более конкретный подкласс - PullRequest
3 голосов
/ 20 июля 2011

Ситуация: у меня есть большое упакованное приложение, которое купила моя компания. Он должен быть расширяемым, Яда, Яда. Он имеет БД, DAL и BLL в виде SQL и DLL. Он также имеет проект MVC (расширяемая часть), но 95% части «Модель» находится в библиотеках DAL / BLL.

Проблема: мне нужно расширить одну из «Моделей», расположенных в BLL. Это объект User с 47 свойствами, 0 методами и без конструктора. То, что я начал, было простым отклонением их класса как:

public class ExtendedUser : BLL.DTO.User
{
    public bool IsSeller { get; set; }
    public bool IsAdmin { get; set; }
}

Это прекрасно работает, если я просто создаю новый ExtendedUser. Однако он заполняется другим вызовом в их BLL, например:

BLL.DTO.User targetUser = UserClient.GetUserByID(User.Identity.Name, id);

Я попробовал прямую попытку грубой силы, которая, конечно, создает исключение броска:

ExtendedUser targetUser = (ExtendedUser)UserClient.GetUserByID(User.Identity.Name, id);

Я рисую полный бланк этой очень простой концепции ОО. Я не хочу писать конструктор, который принимает существующий объект User, а затем копирует каждое из свойств в мой расширенный объект. Я знаю, что есть правильный способ сделать это. Кто-нибудь может дать мне пощечину и сказать очевидное?

ТИА

Ответы [ 3 ]

6 голосов
/ 20 июля 2011

Если вы хотите использовать наследование, то с 47 свойствами что-то вроде Automapper может помочь вам скопировать все значения в - http://automapper.codeplex.com/ - это позволит вам использовать:

// setup
Mapper.CreateMap<BLL.DTO.User, ExtendedUser>();

// use
ExtendedUser extended = Mapper.Map<BLL.DTO.User, ExtendedUser>(user);

В качестве альтернативы вам лучше использовать агрегацию вместо наследования - например,

public class AggregatedUser
{
    public bool IsSeller { get; set; }
    public bool IsAdmin { get; set; }
    public BLL.DTO.User User { get; set; }
}
4 голосов
/ 20 июля 2011

А как насчет этого подхода (в основном агрегация):

public sealed class ExtendedUser  
{
    public ExtendedUser(BLL.DTO.User legacyUser)
    {
        this.LegacyUser = legacyUser;
    }

    public BLL.DTO.User LegacyUser 
    { 
        get; 
        private set; 
    }
} 
2 голосов
/ 20 июля 2011

Я не хочу писать конструктор, который принимает существующий объект User и затем копирует каждое из свойств в мой расширенный объект.

Обычно это «правильный» способ сделать это, если у вас нет времени компиляции с BLL. Проблема в том, что приведение никогда не сработает - ExtendedUser - это конкретный тип User, но каждый User - это не ExtendedUser, который необходим для успешного выполнения приведения .

Вы можете справиться с этим путем агрегации (содержать экземпляр User в качестве члена), но не напрямую через наследование.

Это часто обрабатывается во время компиляции через частичные классы. Если BLL настроен на создание классов (то есть: User) как частичного класса, вы можете добавить свою собственную логику в отдельный файл, что предотвращает возникновение этой проблемы. Это обычная практика для многих более крупных платформ, ORM и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...