Reputation: 2028
Let's say I have a simple class which contains a bunch of attributes or properties:
internal class ConnectionProperties
{
internal string Name = "Default Name";
internal bool Enabled = false;
}
And these are used within a class called Data:
internal class Data
{
private ConnectionProperties _connection;
internal Data()
{
this._connection = new ConnectionProperties();
// Business logic to configure connection
this._connection.Name = "My Connection";
this._connection.Enabled = true; _
}
}
How can I allow external access to the properties and values of _connection WITHOUT allowing them to be changed from anywhere apart from the class Data.
I know I could add a property such as
internal ConnectionName => _connection.Name;
But that feels very messy and could be tough to maintain
Upvotes: 3
Views: 551
Reputation: 1988
You can have read only properties inside your class like this with different levels of encapsulation.
public string Name{get;}
With this you are only able to set the Name only inside the constructor of ConnectionProperties
class.
public string Name{get;private set;}
With this you are only able to set the Name anywhere inside the ConnectionProperties
class and not anywhere else.
public string Name{get;internal set;}
With this you are only able to set the Name anywhere inside the dll not allowing other dlls to set its property.
It all starts from your ConnectionProperties
on how other classes view it.
public class Program
{
public static void Main(string[] args)
{
var data = new Data();
var c = new ConnectionProperties("", false);
data.Connection.Name = ""; // prints readonly error
data.Connection = new ConnectionProperties("", false); //prints readonly error
data.Connection = c; //prints readonly error
}
}
internal class ConnectionProperties
{
internal ConnectionProperties(string name, bool enabled)
{
Name = name;
Enabled = enabled;
}
internal string Name { get; }
internal bool Enabled { get; }
}
internal class Data
{
public ConnectionProperties Connection => new ConnectionProperties("My Connection", true);
internal Data()
{
}
}
Upvotes: 1
Reputation: 10563
If you control the ConnectionProperties
type, you can make it implement an interface, say IReadOnlyConnectionProperties
, that will expose a readonly view of its members.
public interface IReadOnlyConnectionProperties
{
string Name { get; }
bool Enabled { get; }
}
If you don't control the type, you can make such an interface and create a wrapper type that will implement it. It would take ConnectionProperties
in its ctor and proxy get-accesses to it properties. The same way a ReadOnlyCollection
does.
internal ReadOnlyConnectionProperties : IReadOnlyConnectionProperties
{
private readonly ConnectionProperties _wrapped;
public string Name => _wrapped.Name;
public bool Enabled => _wrapped.Enabled;
public ReadOnlyConnectionProperties(
ConnectionProperties connectionProperties) =>
_wrapped = connectionProperties;
}
Note that this assumes a level of trust to the user. If using the first solution, there's nothing stopping the consumers from upcasting the interface back to ConnectionProperties
. The second solution avoids this problem, and is the one I'd recommend. Just remember that in both cases changes to the underlying ConnectionProperties
will be reflected in whatever proxies you give to your consumers.
Upvotes: 4
Reputation: 2836
You can create something like readonly interface for the ConnectionProperties
class and expose it in the Data
class by the readonly interface. This way the ConnectionProprties
will have the same functionality.
internal interface IConnectionProperties
{
string Name { get; }
bool Enabled { get; }
}
internal class ConnectionProperties : IConnectionProperties
{
public string Name { get; set; } = "Default Name";
public bool Enabled { get; set; } = false;
}
internal class Data
{
private ConnectionProperties _connection;
internal IConnectionProperties Connection => this._connection;
}
The only change is that you need to make the ConnectionProperties
's class properties public - Name
, Enabled
.
Upvotes: 1