Простой способ добиться этого - иметь интерфейс, который позволяет читать свойства и вызывать только методы только для чтения, и класс, реализующий этот интерфейс, который также позволяет писать этот класс.
Ваш метод, который его создает, работает с первым, а затем возвращает последний, предоставляя только интерфейс только для чтения, с которым можно взаимодействовать. Это не требует копирования и позволяет легко настраивать поведение, которое вы хотите сделать доступным для вызывающего, а не для создателя.
Возьмите этот пример:
public interface IPerson
{
public String FirstName
{
get;
}
public String LastName
{
get;
}
}
public class PersonImpl : IPerson
{
private String firstName, lastName;
public String FirstName
{
get { return firstName; }
set { firstName = value; }
}
public String LastName
{
get { return lastName; }
set { lastName = value; }
}
}
class Factory
{
public IPerson MakePerson()
{
PersonImpl person = new PersonImpl();
person.FirstName = 'Joe';
person.LastName = 'Schmoe';
return person;
}
}
Единственным недостатком этого подхода является то, что его можно просто привести к классу реализации. Если бы это был вопрос безопасности, то простого использования этого подхода недостаточно. Обходной путь для этого заключается в том, что вы можете создать класс фасадов для переноса изменяемого класса, который просто представляет интерфейс, с которым работает вызывающая программа, и не может иметь доступ к внутреннему объекту.
Таким образом, даже кастинг не поможет вам. Оба могут происходить из одного и того же интерфейса только для чтения, но приведение возвращенного объекта даст только класс Facade, который является неизменным, поскольку он не меняет базовое состояние переносимого изменяемого класса.
Стоит отметить, что это не соответствует типичной тенденции, в которой неизменный объект создается раз и навсегда через его конструктор. Понятно, что вам, возможно, придется иметь дело со многими параметрами, но вы должны спросить себя, нужно ли все эти параметры определять заранее или некоторые из них могут быть введены позже. В этом случае следует использовать простой конструктор с только необходимыми параметрами. Другими словами, не используйте этот шаблон, если он скрывает другую проблему в вашей программе.