Is it possible somehow to achieve this behavior in C#:
public interface IReadOnly
{
Data Value { get; }
}
internal interface IWritable : IReadOnly
{
Admittedly a cop-out, but what I prefer to do is the following:
public interface IReadOnly
{
Data Value { get; }
}
internal interface IWritable : IReadOnly
{
void SetValue(Data value);
}
While Hans Passant's answer works, I find it annoying that with certain inheritance trees, code using a descendant interface can still complain that it doesn't know which version of "Value" you are referring to -- even with the setter!
This isn't a problem:
public interface IReadOnly {
Data Value { get; }
}
internal interface IWritable : IReadOnly {
new Data Value { get; set; }
}
internal class Impl : IWritable {
public Data Value { get; set; }
}
The Impl.Value property implementation takes care of both IReadOnly.Value and IWritable.Value, as demonstrated in this test snippet:
var obj = new Data();
var target = new Impl();
var irw = (IWritable)target;
irw.Value = obj;
var iro = (IReadOnly)target;
System.Diagnostics.Debug.Assert(Object.ReferenceEquals(iro.Value, obj));
Hans Passant gave a very good answer and I've come to a similar answer, but I think I may be able to do one better:
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
}
}
The difference between my and mr. Passant's solution, is that my IReadOnly inherits from my IWritable. As a result of this code, you can't set MyValue within the Program class, which may be how you want it to work. Retrieve and map the data in your Gateway class, but then have it as a read only value beyond that. With that, you have read/write separation.
As an added bonus, the only thing your DAL knows about your objects, is the interface they share as a manner of 'contract'.
Interface Defined Model.
For this to work well, one should declare and implement an IReadWrite, which inherits both IReadable and IWritable, and includes a "new" read-write property. Otherwise an interface that has separate get and set properties, but no get-set property, will be neither readable nor writable.