I have a bunch of enumerations that represent permissions for various parts of the application.
public enum PermissionGroup1
{
CanDo11,
CanDo12,
CanDo13,
}
public enum PermissionGroup2
{
CanDo21,
CanDo22,
CanDo23,
}
public enum PermissionGroup3
{
CanDo31,
CanDo32,
CanDo33,
}
For a given user, I have a collection of all of the user's permissions, and then to check permissions I have a method like:
public Boolean CheckXXXAccess(int ModuleID, PermissionGroupX permission)
{
bool hasAccess = false;
if (!m_Permissions.ContainsKey(ModuleID))
{
hasAccess = false;
}
else
{
hasAccess = (permission == (ModulePermissions[ModuleID].PermissionGroupX & permission));
}
return hasAccess;
}
So to explain it further, the database contains a ModuleID (there is a PermissionGroup enumeration for a given module type), and then I have a method like CheckXXXAccess for each module type.
How can I use generics to make a single method instead of repeating it?
I have implemented it this way.
Say Perms is your ModulePermissions[ModuleID] object's class. Then you could delegate checking access to it like this:
public bool CheckAccess<T>(int moduleId, T perm) {
if(!ModulePermissions.ContainsKey(moduleId)) return false;
return ModulePermissions[moduleId].HasPermission(perm);
}
The Perms implementation:
public class Perms {
List<object> perms = new List<object>();
public bool HasPermission<T>(T perm) {
return perm == (GetPerm(typeof(T)) & perm);
}
dynamic GetPerm(Type permType) {
foreach(var item in perms) {
if(item.GetType() == permType)
return item;
}
throw new Exception();
}
}
That way you can use your new CheckAccess method like this:
bool b1 = CheckAccess(1, PermissionGroup1.CanDo11);
bool b2 = CheckAccess(3, PermissionGroup3.CanDo32);
Of course, you can rewrite HasPermission and GetPerm methods depending on your code rules (e.g. without dynamic and with reflection).
IMO it's better to change your enums to classes, instead of having different enum, have different classes and one enum (with different access level for example Level1, Level2, ... may be some extra level for future), and all of this classes inherit from base class (like PermisionAccessBase) which has one method (currently with this information): CheckAccess (as virtual), and one property which is of type Access Level Enum, All other classes inherit it in the way they want (can override base method but you can have a chance to call to your base).
It doesn't reduce the number of function you should write, but you can put common part of methods in base method and call it in overrided methods, Also it causes to separation of concept, I think the class currently you using for checking permission doesn't made for check permission and if is so, all different permission type checking gathered in one class which is not good.
Related
I'm using Entity Framework. I have a few database tables that store different statistics:
Stats1 (Stats1ID, Mean)
Stats2 (Stats2ID, Mean)
Stats3 (Stats3ID, Mean)
I have multiple methods which I want to consolidate into a single method. The only difference between these methods are the parameters:
public static bool IsValid(Stats1 stat, decimal value) { // }
public static bool IsValid(Stats2 stat, decimal value) { // }
// etc
The methods all use the common field of these different Stat objects - 'Mean'. How do I replace the first parameter with some generic object that I can use to access the Mean field of whichever type is passed in? Not sure if this is relevant but I use "database first" and generate the model like that
edit: appreciate the answers, will test things soon
All Stats classes can implement an interface, say IStat, containing the Mean property. It's enough to extend a generated partial class by another partial class:
partial class Stats1 : IStat { }
EF doesn't mind, as long as you don't use the interface for navigation property types (but you won't with database first).
Then you can define a generic method with a generic type constraint (where):
public static bool IsValid<T>(T stat, decimal value)
where T : IStat
{
// Example of what you could do here:
return stat.Mean > value);
}
Usage:
var valid = IsValid(stat1, 1);
EDIT - Didn't notice you're using Database First. I use this approach in code first, and it probably don't apply to you. But I leave it here in case anyone reads the question later.
You can define an interface that denoted the common field, like:
public interface IStatEntity
{
public int Mean { get; set; }
}
and implement the interface on all of the entities. Implementing an interface does not interfere with EF's mappings and doesn't mean anything to EF.
I use the same approach for having properties such as CreationTime and LastModificationTime and then setting them centrally in my DbContext.
You could use reflection to do what you want.
public static bool IsValid<TStats>(TStats stats, decimal value)
{
if (Equals(stats, null))
return false;
// Get the 'Mean' property
var propertyInfo = typeof(TStats).GetProperty("Mean");
if (Equals(propertyInfo, null))
return false;
// Get
var meanValue = propertyInfo.GetValue(stats, null) as decimal?;
// ... do what ever you want with the meanValue
return meanValue.HasValue && meanValue.Value == value;
}
I have data from multiple organisations (police, fire, office) that need output in different formats.
To achieve this, I defined the following (this is a little simplified):
Transaction class -
"Success" indicator - Boolean.
"Type of department"- String or Enum.
A class which can be of any type - Police, Fire or Office (My question is on this as you will see).
A GenerateOutput() method - to handle generation of file formats.
Police class
Age - String
VehicleNumber - Integer
Supervisor - String
Fire class
Name - String
FireEngineNumber - Integer
County - Enum
WorkTimings - Enum
Office Class
Age - String
DeskNumber - Integer
Department - String
PayScale - Enum
IsManagement - Bool
As you can see, the Police, Fire and Office classes dont share anything in common and are primarily intended as data carrying entities. I intend to use a Factory to return an appropriate generic (not a C# generic) Transaction object with the data (Transaction object with Police, Fire or Office data within it) and then pass the returned object to a Strategy pattern which determines the file format (CSV, Excel, or XML; specified in a configuration file) each one needs.
My problem is in the definition of the Transaction object.
What type does the class in "3." of the Transaction class need to be? The data for each org differs, there are no common members, I am unable to define a common class for all.
Is the overall design appropriate? What other designs should I consider?
Based on Peter's comments below:
I think using generics might work, I ran into a problem though. I would like to use a factory to return the object requested, using GetTransactionObject, as below. What should be the return type of GetTransactionObject to accomodate this.
class TransactionFactory
{
Dictionary<string, Type> typeClassLookup;
public TransactionFactory()
{
typeClassLookup = new Dictionary<string, Type>();
typeClassLookup.Add("Police", typeof(PoliceData));
typeClassLookup.Add("Fire", typeof(FireData));
}
Transaction<????> GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
If the types really have nothing in common, then you need no explicit base class. System.Object suffices, just as with many other generic types (i.e. any generic type lacking a constraint).
In other words, you could declare as:
class Transaction<T>
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { /* something goes here */ }
}
Personally, I would avoid adding a "department type" member. After all, that's implicit from the type parameter T. But you could add that easily to the above if you want.
If and when you find that the types do have something in common, such that your Transaction<T> type needs to do more than simply hold onto an instance of one of those types (which is about all it can do without a constraint), then you will be able to put that commonality into an interface or base class (depending on the specific need), and specify that in a constraint for the Transaction<T> class.
Note that it's not clear what you mean for the GenerateOutput() to do, or how it should work. But assuming that you want output that is specific for each Entity value, it seems to me that that is your "something in common". I.e., it's not the Transaction<T> class at all that needs to implement that method, but rather each entity type. In that case, you have something like this:
interface IDepartmentEntity
{
void GenerateOutput();
}
class Office : IDepartmentEntity
{
public void GenerateOutput() { /* department-specific logic here */ }
}
// etc.
Then you can declare:
class Transaction<T> where T : IDepartmentEntity
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { Entity.GenerateOutput(); }
}
EDIT:
Per Prasant's follow-up edit, with a request for advice on the GetTransactionObject()…
The right way to do this depends on the caller and the context, a detail not provided in the question. IMHO, the best scenario is where the caller is aware of the type. This allows the full power of generics to be used.
For example:
class TransactionFactory
{
public Transaction<T> GetTransactionObject<T>()
where T : IDepartmentEntity, new()
{
return new Transaction<T>()
{
Data = new T(),
params = null
}
}
}
Then you call like this:
Transaction<FireData> transaction = factory.GetTransactionObject<FireData>();
The caller, of course already knowing the type it is creating, then can fill in the appropriate properties of the transaction.Data object.
If that approach is not possible, then you will need for Transaction<T> itself to have a base class, or implement an interface. Note that in my original example, the IDepartmentEntity interface has only one method, and it's the same as the GenerateOutput() method in the Transaction class.
So maybe, that interface is really about generating output instead of being a data entity. Call it, instead of IDepartmentEntity, something like IOutputGenerator.
In that case, you might have something like this:
class Transaction<T> : IOutputGenerator
{
// all as before
}
class TransactionFactory
{
public IOutputGenerator GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
}
}
This is an inferior solution, as it means the caller can only directly access the IOutputGenerator functionality. Anything else requires doing some type-checking and special-case code, something that really ought to be avoided whenever possible.
Note: if the Transaction type has other members which, like the GenerateOutput() method, are independent of the contained type T here, and which would be useful to callers who don't know T, then a possible variation of the above is to not reuse the interface used for the department-specific data types, but instead declare a base class for Transaction<T>, named of course Transaction, containing all those members not related to T. Then the return value can be Transaction.
What type does the class in "3." of the Transaction class need to be?
To decouple your department classes from the various export types, I recommend you make the department classes implement a common interface. Something like this:
public interface Exportable {
// return a list of attribute names, values, and types to export
IList<Tuple<String, String, Type>> GetAttributes();
}
For example:
public class Police : Exportable {
public IList<Tuple<String, String, Type>> GetAttributes() {
// return list size 3 - attribute info for Age, VehicleNumber, Supervisor
}
}
Is the overall design appropriate? What other designs should I consider?
The Transaction class design doesn't seem well suited for this problem.
Consider an Export class with a method for each export type, each method which receives the attributes returned from the Exportable interface method. Basic outline:
public static class Export {
public static boolean CSV(IList<Tuple<String, String, Type>> attributes) {
// export attributes to CSV, return whether succeeded
}
public static boolean Excel(IList<Tuple<String, String, Type>> attributes) {
// export attributes to Excel, return whether succeeded
}
// same thing for XML
}
This page on the PostSharp website has the following teaser:
One of the common situations that you will encounter is the need to implement a specific interface on a large number of classes. This may be INotifyPropertyChanged, IDispose, IEquatable or some custom interface that you have created.
I'd like to write a custom aspect that implements a general version of IEquatable based on the properties of the class it's applied to (preferably at compile-time instead of by using reflection at runtime). It would be good to just be able to add an attribute to a simple class rather than having to implement a custom method each time. Is that possible? I'd hope so, since it's specifically called out in this introduction, but I haven't been able to track down any example code.
I've seen this example from the PostSharp website that includes an example of introducing the IIdentifiable interface. But it just returns a GUID that's independent of the class that the new interface is added to.
Is there a way to construct a custom attribute that implements IEquatable based on the properties of the type that it's applied to (i.e. making two instances equal if all of their properties are equal)?
I've found a solution using T4 templates but would like to know if the same can be achieved using PostSharp.
Edit:
To be clear, I'd like to be able to write something like this:
[AutoEquatable]
public class Thing
{
int Id { get; set; }
string Description { get; get; }
}
and have it automatically converted to this:
public class Thing
{
int Id { get; set; }
string Description { get; get; }
public override bool Equals(object other)
{
Thing o = other as Thing;
if (o == null) return false;
// generated in a loop based on the properties
if (!Id.Equals(o.Id)) return false;
if (!Description.Equals(o.Description)) return false;
return true;
}
}
This is possible with PostSharp 4.0 using the following code;
[PSerializable]
class EquatableAttribute : InstanceLevelAspect, IAdviceProvider
{
public List<ILocationBinding> Fields;
[ImportMember("Equals", IsRequired = true, Order = ImportMemberOrder.BeforeIntroductions)]
public Func<object, bool> EqualsBaseMethod;
[IntroduceMember(IsVirtual = true, OverrideAction = MemberOverrideAction.OverrideOrFail)]
public new bool Equals(object other)
{
// TODO: Define a smarter way to determine if base.Equals should be invoked.
if (this.EqualsBaseMethod.Method.DeclaringType != typeof(object) )
{
if (!this.EqualsBaseMethod(other))
return false;
}
object instance = this.Instance;
foreach (ILocationBinding binding in this.Fields)
{
// The following code is inefficient because it boxes all fields. There is currently no workaround.
object thisFieldValue = binding.GetValue(ref instance, Arguments.Empty);
object otherFieldValue = binding.GetValue(ref other, Arguments.Empty);
if (!object.Equals(thisFieldValue, otherFieldValue))
return false;
}
return true;
}
// TODO: Implement GetHashCode the same way.
public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
{
Type targetType = (Type) targetElement;
FieldInfo bindingField = this.GetType().GetField("Fields");
foreach (
FieldInfo field in
targetType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic))
{
yield return new ImportLocationAdviceInstance(bindingField, new LocationInfo(field));
}
}
}
I'm afraid this can not be done with PostSharp. PostSharp "injects" aspects code in your clases but you have to code the aspects. The key here is indetify common behavior and cross cutting concern in your system and model it as Aspects.
In the example of IIdentifiable you can see how GUID is a unique identifier that can be use by a lot of different classes in your system. It is common code, it is cross cutting concern and you find yourself REPEATING code in all your class entities so Identificable can be modeled as Aspect and get rid of repeating code.
As diferent classes has diferent Equals implementation you can not "deatach" (convert to aspect) the implementation of Equals. Equals is not a common behavior. Equals is not cross cutting concern. Equals can not be an Aspect (without reflection).
I have an attribute that I am using to decorate object properties with. The attribute identifies the properties as needing validation to be performed on them. I am essentially implementing the Strategy Pattern and building all of the validation (really only about 6 types) in to individual objects that I can use across multiple classes. What I want to do, is provide parameters to the validation classes, without having to create an attribute for each validation object variation.
My attribute looks like this:
[AttributeUsage(AttributeTargets.Property)]
public class ValidationRuleAttribute : Attribute
{
public ValidationRuleAttribute(Type validationRule, string customFailureMessage = "")
{
if (typeof(IValidationRule).IsAssignableFrom(validationRule))
{
this.ValidationRule = string.IsNullOrEmpty(customFailureMessage)
? Activator.CreateInstance(validationRule, customFailureMessage) as IValidationRule
: Activator.CreateInstance(validationRule) as IValidationRule;
}
else
{
throw new ArgumentException(
string.Format(
"ValidationRule attributes can only be used with IValidationRule implementations. The '{0}' Tyoe is not supported.",
validationRule.Name));
}
}
public IValidationRule ValidationRule { get; private set; }
}
As an example, I have a simple StringIsNotNull validation object. I want to expand on it by allowing me to specify a minimum string length requirement. So the StringIsNotEmptyValidation would become StringHasMinimumLengthValidation
public class StringIsNotEmptyValidation : IValidationRule
{
private readonly string customErrorMessage;
public StringIsNotEmptyValidation()
{
}
public StringIsNotEmptyValidation(string customErrorMessage)
{
this.customErrorMessage = customErrorMessage;
}
public string ResultMessage { get; private set; }
public IValidationMessage Validate(System.Reflection.PropertyInfo property, IValidatable sender)
{
string value = property.GetValue(sender).ToString();
// Validate
bool isFailed = string.IsNullOrWhiteSpace(value);
if (isFailed)
{
if (string.IsNullOrEmpty(this.customErrorMessage))
{
DisplayNameAttribute displayName = property.GetCustomAttribute<DisplayNameAttribute>(true);
string errorMessage = displayName == null
? string.Format("You can not leave {0} empty.", property.Name)
: string.Format("You can not leave {0} empty.", displayName.DisplayName);
this.ResultMessage = errorMessage;
return new ValidationErrorMessage(errorMessage);
}
else
{
this.ResultMessage = this.customErrorMessage;
return new ValidationErrorMessage(customErrorMessage);
}
}
this.ResultMessage = string.Empty;
return null;
}
}
Within my model, I decorate my property with the attribute and validation object.
[RepositoryParameter(DbType.String)]
[ValidationRule(typeof(StringIsNotEmptyValidation))]
public string WorkDescription
{
get
{
return this.workDescription ?? string.Empty;
}
set
{
this.SetPropertyByReference(ref this.workDescription, value);
if (this.HasValidationMessageType<ValidationErrorMessage>(this.GetPropertyName(p => p.WorkDescription)))
{
this.Validate();
}
}
}
What I want to do, is write my attribute usage like this:
[ValidationRule(new StringIsNotEmptyValidation(minimumLength: 4))]
Since you can't instance objects in an attribute constructor, I'm forced to provide the attributes in my attribute constructor like this:
[ValidationRule(typeof(StringIsNotEmptyValidation), minLength: 4)]
I don't like this because if I have a ObjectIsNotNull or a StringIsInRange I will need to do two things:
Create a new attribute for each parameter variation (or a lot of overloads)
Set up the validation rule instances within the constructor, which will have varying property names.
The Validation object implements the following interface
public interface IValidationRule
{
string ResultMessage { get; }
IValidationMessage Validate(PropertyInfo property, IValidatable sender);
}
I don't want to bloat my interface with a large number of properties that might be used or might not be used depending on the Rule implementing it. It also makes it difficult to assign attribute params to the rule object.
So my question is how can I provide parameters to the IValidationRule concrete classes, without creating multiple attribute types to facilitate this? This is being used so that I an do cross-object validation. The PropertyInfo passed in to the validation rule is from a cache of PropertyInfo's. I need to keep the amount of reflection used down, otherwise I'd just use attributes for each rule parameter and use reflection on sender to figure out what ranges to use.
Update
After discussing this with Corey, it does indeed appear that attributes are supported in Universal Apps and it is only the DataAnnotations namespace that is missing. In order to get access to the attributes, I had to add a using statement to System.Reflection in order to gain access to a series of extension methods that expose the GetCustomAttribute methods. They are now extension methods and not built in to the Type class.
So I suppose in the end, I can just create my validation logic within the attributes, instead of individual objects. I can't think of any downsides to going this route.
In order to access the attributes in a Universal App, you have to include System.Reflection as a using statement, then access via the GetRuntimeProperties() extension method.
var validationRule = this
.GetType()
.GetRuntimeProperties() // Can be GetRuntimeFields or GetRuntimeMethods as well.
.FirstOrDefault(p => p.GetCustomAttribute<IntegerInRangeAttribute>() != null);
So there are a few options here.
First, and often used, is to have a different attribute for each type of rule you want to process. You are already building classes for each of your rules, so instead of having some encapsulating attribute that instantiates them all just make each rule an attribute:
[StringMinLengthRule(5)]
public string SomeString { get; set; }
Build the validation logic into your attributes - say with a base attribute that does the bulk of the work, calling a virtual method to do the actual validation. Then you can just enumerate the rule attributes and call them from your validation method.
Next, you can have a number of different properties on your attribute that can be set during declaration to provide the properties for your various rules:
[Validation(RuleType.StringMinLength, MinLength = 5)]
public string SomeString { get; set; }
You could still have the rules be processed in the ValidationAttribute itself, or create IValidationRule instances at run-time to process the actual validations. Unfortunately there's nothing to stop you from adding a Validation attribute that sets the wrong properties for the rule type, resulting in errors at run-time when you try to validate an instance.
Finally, something that works but probably shouldn't... and it's kinda ugly:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ValidationRuleAttribute : Attribute
{
public IValidationRule ValidationRule { get; private set; }
public ValidationRuleAttribute(RuleType type, params object[] parms)
{
if (type == RuleType.NotNull)
{
if (parms.Length != 0)
throw new ArgumentException("RuleType.NotNull requires 0 parameters", "parms");
ValidationRule = new NotNullValidation();
}
if (type == RuleType.StringMinLength)
{
if (parms.Length != 1)
throw new ArgumentException("RuleType.StringMinLength requires 1 parameter", "parms");
if (!(parms[0] is int))
throw new ArgumentException("RuleType.StringMinLength requires an integer", "parms");
ValidationRule = new StringLengthValidation((int)parms[0]);
}
}
}
The biggest problem with it is that it won't complain until you try to instantiate a class at run-time that has a bad Validation attribute. Your code can run quite happily up until the point where it tries to create an instance of that bad class, at which point all of the attributes will actually be constructed and those ArgumentExceptions start flying.
In fact only the first option doesn't suffer from run-time problems, because you can control the types of parameters being supplied by using the correct constructor formats. You can still tell it to do silly things - like requiring that strings must have less than 0 length for instance - but that's up to you :P
Its typical to expose internal data structures as properties to your business class. But when we have to expose array-like structures (like List<Rule> rules) we might encounter a problem of wrong usage (as in Option 1).
Its suggested to expose clone of such data structures as properties, so that internal structure does not get disturbed.
Does any one have a well-settled solution for this?
public class Rule
{
}
public class RulesManager
{
List<Rule> rules = new List<Rule>();
public List<Rule> Rules
{
get { return rules; }
set { rules = value; }
}
public void Add(Rule r)
{
rules.Add(r);
// Do something else after add;
}
public void Delete(Rule r)
{
rules.Remove(r);
// Do something else after delete;
}
}
public class CallingCode
{
public static void Main()
{
RulesManager r = new RulesManager();
// Option 1
r.Rules.Add(new Rule());
// Option 2
r.Add(new Rule());
}
}
Instead of returning a Clone, you can return a read-only version of rules using rules.AsReadOnly().
public IList<Rule> Rules
{
get { return rules.AsReadOnly(); }
// set { rules = value; -- should not be allowed to set if read only!
}
Note the IList.
Instead of returning a List you can return an IEnumerable. The IEnumerable allows the user to iterate through the collection, but it doesn't allow the user to modify it easily.
Alternatively you could return an arryay instead of a list. This will create a copy of the list that the user cannot easily modify.
Finally you should be aware that the user might also modify the contents of the collection. This may be what you want, but you might also want to return copies of your items.
I think it is quite common to expose the IList as a property, but I prefer to expose only explicit Add/Delete functions. You can also consider to implement one of the collection interfaces in your class (IList for instance), if you are developing something more of a framework.
Instead of:
public List<Rule> Rules
{
get { return rules; }
set { rules = value; }
}
I prefer to implement IEnumerable<T> and an indexer on the class, so that I have control over what happens to the list.
Check out the ReadOnlyCollection and the AsReadOnly() List method.
A basic workaround is to use List<T>.AsReadOnly() method, which will wrap the list around a ReadOnlyCollection to block any "write" access. Of course, you'd have to make the setter private, otherwise it would not make sense...
Another alternative would be to implement your own IList that would alert you in case of "write" access and allow you to perform your business logic.