I am trying to create an interface or an abstract class that would serve as a base for many Authorization objects.
My idea is as follows (code that does not compile but I'd like to work):
public abstract class AuthObject {
public Enum Values;
public abstract AuthObject AddPermission(Values permission);
}
An implementation the would look like this:
public class AuditLogManagement : AuthObject {
private long _permissions;
public new enum Values {
None = 0,
Read = 1,
Search = 2,
Filter = 4,
Export = 8
}
public AuthObject AddPermission(AuditLogManagement.Values permission) {
_permissions |= (long)permission;
return this;
}
}
The main point of my question is how to limit parameter to AddPermission() to only this object Values field (Enum) in an interface or abstract class. However I cannot find a way to do it.
Thank You for any ideas.
Edit:
A little more simplified use case to explain the requirements:
interface I {
AddPermission(I.Values permission);
}
class A : I {
private long _permissions;
public enum Values {
A_a, A_b, A_c
}
AddPermission (this.Values newPermission) {
_permissions |= newPermission;
}
}
class B : I {
private long _permissions;
public enum Values {
B_a, B_b, B_c
}
AddPermission (this.Values newPermission) {
_permissions |= newPermission;
}
}
var classA = new A();
var classB = new B();
A.AddPermission(A.Values.A_a); // Allowed
A.AddPermission(B.Values.B_c); // Forbidden! B_c value equals to A_c but is not the same permission!
I would reach for generics:
public abstract class AuthObject<T>
where T : struct, IConvertible // A reasonable way to constrain to an enumeration.
// you can also use System.Enum for newer versions of C# past 7.3 I believe.
{
public T Values { get; }
public abstract AuthObject<T> AddPermission(T permission);
}
public enum Values
{
None = 0,
Read = 1,
Search = 2,
Filter = 4,
Export = 8
}
public class AuditLogManagement : AuthObject<Values>
{
private long _permissions;
public AuthObject AddPermission(Values permission)
{
_permissions |= (long)permissions;
return this;
}
}
The only other suggestion I would give on top of this is to name the 'T' parameter above to something a little more descriptive, like 'TPermission' since you aren't using it for the typical container class.