Ханс Пассант дал очень хороший ответ, и я пришел к аналогичному ответу, но я думаю, что смогу сделать лучше:
public interface IReadOnly : IWritable
{
new int MyValue { get; }
}
public interface IWritable
{
int MyValue { get; set; }
}
public class Implementation : IReadOnly
{
public int MyValue { get; private set; }
int IWritable.MyValue
{
set { MyValue = value; }
get { return MyValue; }
}
public static Implementation GetMyImplementation()
{
return ImplementationGateway<Implementation>.GetMyImplementation();
}
}
public class ImplementationGateway<TImplementation>
where TImplementation : class, IWritable, new()
{
public static TImplementation GetMyImplementation()
{
return new TImplementation
{
MyValue = 1
};
}
}
public class Program
{
public Program()
{
Implementation myImplementation = Implementation.GetMyImplementation();
myImplementation.MyValue = 0; //This will and is supposed to fail
}
}
Разница между моим и мистером. Решение Passant заключается в том, что мой IReadOnly наследуется от моего IWritable. В результате этого кода вы не можете установить MyValue в классе Program, который может быть таким, каким вы хотите, чтобы он работал. Извлеките и отобразите данные в вашем классе Gateway, но затем установите их в качестве значения только для чтения. С этим у вас есть разделение чтения / записи.
В качестве дополнительного бонуса, единственное, что ваш DAL знает о ваших объектах, - это интерфейс, который они используют в качестве «контракта».
I nterface D определено M odel.