2009-11-19 5 views
0

Я заинтересован в создании неизменяемого класса, который имеет свойства, которые нельзя изменить, и изменяемый класс, который вытекает из него. Эти объекты будут простыми объектами данных, представляющими записи базы данных, поэтому они будут иметь только неизменные значения для свойств.Любой способ сделать изменяемый объект, полученный из неизменяемого объекта в C#?

Моя цель состоит в том, чтобы мой уровень доступа к данным создавал изменчивые версии объектов, обычно устанавливая свойства на основе значений базы данных, но передавая версии приложения только для чтения обратно в приложение. (Я в порядке с тем, что код мог явным образом отбросить неизменяемый объект обратно в изменчивый, если разработчик действительно захотел.)

Я могу сделать это уродливо (это слово?), Используя методы для добытчики и сеттера и имеющие публичный новый сеттер для изменяемого класса:

public class ImmutableClient { 
    private int _clientId; 
    public int getClientId() { return _clientId; } 
    protected void setClientId(int clientId) { _clientId = clientId; } 
} 

public class Client : ImmutableClient { 
    public new void setClientId(int clientId) { base.setClientId(clientId); } 
} 

Я предпочитаем использовать авто-свойство, если это возможно - они намного лучше при отладке. Кроме этого, мне все равно, как выглядит код, потому что он просто исходит из генератора кода и никогда не рассматривается.

Любые идеи?

ответ

3

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

interface IReadOnlyObject 
{ 
    int Property { get; } 
} 

class DALObject : IReadOnlyObject 
{ 
    public int Property { get; set; } 
} 
+0

Это прекрасно - я думал, что у меня на уме, что я даже не думал об интерфейсах, но это абсолютно сработало для моего сценария. Большое спасибо. –

2

Вы можете иметь ваш слой данных возвращают только для чтения интерфейс:

interface IClient 
{ 
    int getClientId(); 
} 

Тогда вам не нужно заботиться, если ваша конкретная реализация имеет сеттер или нет - ваши абоненты будут использовать только геттер.

В качестве примечания - ваш код выглядит как Java, чем C#, так что я бы на самом деле использовать:

interface IClient 
{ 
    int ClientId { get; } 
} 
+0

Perfect - похоже, что вы и Мэтт ответили почти в одно и то же время ... Мне не нравится синтаксис, подобный Java, но в моем примере мне пришлось держать их в отдельности, если я хотел реализовать только getter in неизменяемая версия - способ, подобный Java, был единственным способом, о котором я мог думать в то время. Интерфейсы будут идеальными - спасибо. –

0

Неизменные означает неизменным. Когда я вижу, что тип неизменен, я знаю, что я могу кэшировать его и работать с ним несколько раз, не изменяя его. Сопротивляемое состояние делает это предположение бесполезным.

class Foo 
{ 
    // I'm immutable 
} 

class Bar : Foo 
{ 
    // I add mutable properties 
} 

... 

void F(Foo foo) 
{ 
    // foo is immutable - therefore Bar (mutable) *cannot* be derived from Foo. 
} 
+0

Спасибо - я думаю, что «неизменный» не был правильным словом для описания моей цели. Мне просто нужен объект, который разработчик не мог легко изменить во внешнем коде. Это не поистине неизменное, просто практически неизменное. Конечно, из того, что я могу сказать, действительно нет такой вещи, как действительно неизменяемое поле - как только вы получите отражение в игре, возможно изменение приватных полей readonly. –

0

Имейте базовый класс, который не дает никаких мутаторов, но не дает обещания неизменности. Получают производный неизменяемый класс и отдельно изменяемый класс. Все классы должны иметь конструктор, который принимает базовый класс, и перегружаемое/перегруженное свойство «AsImmutable», которое вернет объект неизменяемого производного класса либо путем вызова конструктора, либо (если объект уже имеет неизменяемый класс), возвращающего сам.