20

Sorry for the terrific Title for the post. I am bit curious to know if below problem does have any solutions or not. The situation is I have a function called SaveSecurity(); which I need to call after every function. Like below:

public void AddUser(string ID, string Name, string Password)
{
    ///some codes
    SaveSecurity();
}
public void DeleteUser(User ObjUser)
{
    ///some codes
    SaveSecurity();
}
public void AddPermission(string ID, string Name, AccessType Access)
{
    ///some codes
    SaveSecurity();
}
public void DeletePermission(Permission ObjPermission)
{
    ///some codes
    SaveSecurity();
}
public void AddRole(string ID, string Name)
{
    Roles.AddRole(ID, Name);
    SaveSecurity();
}
public void SaveSecurity()
{
    ///Saves the data
}

And many more. So now if we look there is a similarity to all the function is that at last it calls for the SaveSecurity() after the end of the function. My question is:

Is there a way to call this function after every function with out writing the same line again and again?

My Class Diagram looks like this

enter image description here

Shweta Pathak
  • 775
  • 1
  • 5
  • 21
  • 1
    You could consider aspect approach (f.e. PostSharp), but even in that case, you will have to specify (f.e. via attribute) which methods should call `SaveSecurity`... – pwas Oct 12 '15 at 07:20
  • 2
    You may want to check out [AOP](https://en.wikipedia.org/wiki/Aspect-oriented_programming). There are several AOP solution/framework in .NET world, like Spring.NET, PostSharp and a few IoC containers. See http://stackoverflow.com/questions/633710/what-is-the-best-implementation-for-aop-in-net – qxg Oct 12 '15 at 07:20
  • 5
    Of course AOP comes mind, but I think it is the wrong tool for this problem, because it is not another "concern" like for example logging. For me, SaveSecurity() is essential to the methods and should be put directly into them... – Rico Suter Oct 12 '15 at 07:29
  • 3
    @RicoSuter If it is essential, then don't automate it by moving it somewhere you may 'forget' it sometime it exist. Code needs to be very precise and clear. And I think, if it is a mandatory part of the function you either write it everytime or you extract it a helper class and apply something like the [template method pattern](https://sourcemaking.com/design_patterns/template_method) – ckruczek Oct 12 '15 at 07:32
  • @RicoSuter: Acutally I agree with you. I wasnt able to say this bcoz of lack of words to describe it. Thanks for describing. :) – Shweta Pathak Oct 12 '15 at 07:33
  • Yes, this is what I meant ;) – Rico Suter Oct 12 '15 at 07:33
  • @ShwetaPathak you want to follow OOP but your code isn't following it, you need to show us your class diagram first to get proper feedback, in other words you are just doing functional programming with blend of OOP. Try looking into repository pattern and then find problem to your solution – Mathematics Oct 12 '15 at 07:40
  • You may need to seperate classes like permissions, user and roles, then create another class Data or something, + add another layer which will be doing business logic calling several methods in a single method – Mathematics Oct 12 '15 at 07:42
  • Are you into an ASP.NET application? – Emanuele Greco Oct 12 '15 at 07:42
  • @EmanueleGreco: It is a WPF, C#, Service Library. – Shweta Pathak Oct 12 '15 at 08:00
  • You could write a function that takes a Lambda, executes it, then runs the security functions before returning. – Carcigenicate Oct 12 '15 at 11:22

4 Answers4

9

You need to look into repository pattern,

Seperate your classes and there operations,

Create another layer (call it business layer) or whatever which will be calling different methods of different classes...

ATM you are trying to follow OOP but all you are doing is functional programming..

Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application

Edit After adding class diagram

Your collection classes are actually repository class, you will need to move your methods like deletePermissions, deleteRole to there respective repository classes like permissionsRepo (keep it named as collections if you want) and roleRepo..

So you already have an object class and a repository class of object (can be together) but I like to keep them separate, repostory classes will do what they need to do, like..

// Make changes to DB
// Make changes to AD
// Makes changes to web services etc...

Your manager class may dulicate methods of repository classes but they will only calling them,

PermissionManager.DeletePermissions(PermissionObject);

Then in PermissionManager Class you will have method,

DeletePermissions(Permissions pObject)
{
     PermissionRepo.Delete(pObject);
}

Above is just adding a layer to make your code look more readable and future proof in very short time, but if you have more time to invest you can look into Observer pattern too...

Implement Observer pattern in C#

Each time your object changes it's state you can call SaveSecurity method (which will be in another class (Name it Changes maybe). If you don't want to call SaveSecurity for each change of object, you can add a property to your object e.g. IsSecurityChanged ? if yes then call SaveSecurity.

More to explain but if you look at Observer pattern above you will get an idea.

One more way but I won't personally recommend is, to use IDisposable interface, then in dispose method call SaveSecurity method for the object. BUT ITS NOT RECOMMENDED BY ME.

Mathematics
  • 7,314
  • 25
  • 77
  • 152
7

With just C# you can't, but there are some solutions that might help.

The best I know is PostSharp. It will give you the ability to define actions before and after a method is being called (for example). Some information on it can be found here and here.

The only thing you have to do then is to decorate the methods you want to call SaveSecurity for with an attribute.

If you don't want to use such tools, just keep it as is. It is okay the way it is.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Let me have a look. Its new for me and thus a new knowledge for me. Hope that would help me. – Shweta Pathak Oct 12 '15 at 07:31
  • You said he can't with just C#, but I think it should be possible through introspection alone... – Shautieh Oct 12 '15 at 11:01
  • @sha can you give an example? – Patrick Hofman Oct 12 '15 at 11:06
  • The most similar thing I did (I didn't keep the source code so...) was to inspect methods of classes, get their body and make new functions out of this. I don't know if it's possible to replace the original body, but if it is then it would answer the question. – Shautieh Oct 12 '15 at 11:41
  • 2
    How is requiring an attribute decorator before each method any better than requiring a function call at the end? You're just as likely to forget one as the other, and it doesn't solve the problem of duplicated code, just moves it from the bottom to the top of the method. At best, this might increase the visibility of it, making it easier to see if you missed one, but really it just adds another moving part, which invites more room for error. – Darrel Hoffman Oct 12 '15 at 13:09
  • That is true to some extend. That is why I said this code in basis is okay. What if the line isn't just one method call without parameters, but a bunch of code? Then it might come in handy to use aspects. @DarrelHoffman – Patrick Hofman Oct 12 '15 at 13:10
5

You can use some kind of Aspect oriented programming (don't know how to do it in C#, but try googling it).

Another way that would not be better than simply calling one function at the end of another, would be create helper function with functional parameter that execute its parameter and then call your security function. But then body of each function would look something like (if I remember C# lambda correctly):

CallAndSaveSecurity(() => /* some code */);

So it would contain something extra as much as your original solution.

Btw, maybe you need more in your call anyway. If you want that function to be called even when exception happen, you need

try{
  // some code
} finally {
  SaveSecurity();
}

and hiding that into functional helper makes sense.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
Alpedar
  • 1,314
  • 1
  • 8
  • 12
3
using System;

namespace Shweta.Question
{
   public class User
   { }
   public class Permission
   { }

   public enum AccessType
   {
      none,
      full,
      other
   }

   public class Roles
   {
      public static void AddRole(string id, string name)
      {
      }
   }

   public class Shweta
   {
      public void AddUser(string ID, string Name, string Password)
      {
         ///some codes
         SaveSecurity();
      }
      public void DeleteUser(User ObjUser)
      {

      }
      public void AddPermission(string ID, string Name, AccessType Access)
      {

      }
      public void DeletePermission(Permission ObjPermission)
      {

      }
      public void AddRole(string ID, string Name)
      {
         Roles.AddRole(ID, Name);
      }
      public void SaveSecurity()
      {
         ///Saves the data
      }

      public TResult CallMethod<TResult>(Func<TResult> func)
      {
         try
         {
            return func();
         }
         catch (Exception e)
         {
            // Add Handle Exception

            // replace the next line by exception handler
            throw e;
         }
      }

      public void CallMethod(Action method)
      {
         this.CallMethod(() => { method(); return 0; });

         this.SaveSecurity();
      }

      public static void test()
      {
         var s = new Shweta();
         s.CallMethod(() => s.AddRole("theId", "theName"));
         s.CallMethod(() => s.DeleteUser(new User()));
         s.CallMethod(() => s.AddPermission("theId", "theName", AccessType.full));
         s.CallMethod(() => s.DeletePermission(new Permission()));
         s.CallMethod(() => s.AddRole("theId", "theName"));
      }
   }
}
herny
  • 31
  • 1
  • I like the idea, but what's preventing me from calling DeleteUser since it's a public method? Looks like DeleteUser won't call SaveSecurity. – jones-chris Oct 31 '17 at 15:03