简体   繁体   中英

Executing one Method At the Start of Several other Methods

i probably dont have the right words but i have tried my best.

say i have a function in c# such as DoWork and within that function i want to call another function such as CheckScore(). However, CheckScore() is a generic function that i want to call from multiple places.

So in my class when i create another function DoWork2, DoWork3 is there any way i can execure CheckScore() as the first line instead of typing those everytime?

For eg. can i avoid

string DoWork2(){
CheckScore()
}

Instead just have

string DoWork2(){}

but CheckScore() is executed anyways?

One potential, though still not foolproof, method is to abstract your security checks into Attributes. This way you can decorate your methods with something like:

[CheckToken]
public string DoWork() {
  ....
}

This isn't necessarily the best answer because it still requires you to attribute the method. You could instead create an attribute for your web service class, which would execute the [CheckToken] on any method call of the class.

[CheckToken]
public class MyWebService {
   ...
}

The only issue here is if you have some methods where you want to execute different security checks, or no security checks.

AC# web service framework that has pretty good security features baked into the framework is Service Stack. http://www.servicestack.net/ It has security attributes already built in that you can use, and it promotes clean separation of concerns.

Another very robust option involves intercepting method calls. C# has a class "ContextBoundObject" which can be used for this purpose. You'd need to have your class inherit from ContextBoundObject, and then you can start to dynamically intercept method calls and perform your security checking based upon the context of the method call being made and its parameters. ContextBoundObject does add some overhead to your calls, so you'll need to factor that into your decision. Method interception is great for things like security, performance monitoring, health checks, method retries, and other cross cutting concerns.

Here's a simple getting-started article on ContextBoundObject (and Aspect Oriented Programming). http://www.codeproject.com/Articles/8414/The-simplest-AOP-scenario-in-C

For J...

I wouldn't have the method code query the result. Since we're talking about a web service, there's a pipeline involved where a request is initiated by a client, that request is sent to the service, that service initializes its handlers, deserializes the request, routes the request to the appropriate method, executes the method, serializes the response, and returns the response to the client (this is a big simplification..). Most frameworks I've seen have some hooks for you to specify attributes on your service methods that get checked at the point prior to method execution and can be used to handle security (ie, return a 401 http code for a web service). I believe he said he's using WCF and while it's been a while since I've used WCF, I know this can be done - see http://msdn.microsoft.com/en-us/library/ms733071.aspx

So he could derive his custom security attribute from some WCF security attribute and create his own authentication logic based upon some token, which he'd most likely have to grab from the headers of the request. ServiceStack makes this super easy, I'd imagine it's not that hard using WCF either. Chances are someone's already done this for WCF and the code is out there somewhere.

This may not be exactly what you are looking for, but I would associate the "CheckScore" with the getter for the property when the score is accessed. That way, when using the property it feels like you are not writing out the CheckScore a lot, and also you don't have a CheckScore function being called every time any old method is invoked in your application.

    private int _score;

    public int Score
    {
        get
        {
            CheckScore();
            return _score;
        }
    }

    public void DoWork1()
    {
        if (Score > 10) { 
           // Case 1
        }
    }

    public void DoWork2()
    {
        if (Score < 20) { 
          // Case 2
        }
    }

Given the additional information in comments, one solution to this problem is to create a small class to encapsulate methods which require authentication :

abstract class AuthenticateClass
{
    private bool AuthenticateUser(){
        return true;  // do your authentication
    }
    public int Perform(){
        if (!AuthenticateUser()){
            return -1;
        } else 
            return AuthenticatedMethod();
    }

    protected abstract int AuthenticatedMethod();
}

This gives you a class that performs the authentication and, if successful, performs your method. Implement it like :

class SomeAuthentMethod : AuthenticateClass 
{
    protected override int AuthenticatedMethod()
    {
        return 10; // whatever method...
    }
}

and use it like :

 SomeAuthentMethod myMethod = new SomeAuthentMethod();
 if (myMethod.Perform() = -1){
     //  unable to authenticate user, please log in, etc
 }

If the authentication passes this returns 10 , otherwise it returns -1 (authentication failed). This lets you generate any number of methods which automatically include authentication.

Alternatively, you might use a static class to do the authentication -- for example :

static class Authenticate
{
    public delegate int MethodDelegate();

    private static bool AuthenticateUser(){
        return true;    // do your authentication
    }
    public static int Perform(MethodDelegate MyMethod){
        if (!AuthenticateUser())
        {
            return -1;
        }
        else return MyMethod();
    }
}

Where you could then have :

private int myMethod(){
        return 10;  //whatever method...
}

and then implement like :

if (Authenticate.Perform(myMethod) = -1){
     //  unable to authenticate user, please log in, etc
 }

Obviously you can extend both of these patterns to handle whatver "not logged in" or "not authenticated" action within the abstract or static class itself. This should, at least, provide a few ideas of how to approach the problem.

Putting CheckScore in a property will still result in it being called a lot.

You could use a private readonly field and set it in the constructor. This will minimise the number of calls to CheckScore.

public class MyClass
{
    private readonly int _score;

    public MyClass()
    {
        _score = CheckScore();
    }

    public int Score
    {
        get
        {
            return _score;
        }
    }

    public void DoWork1()
    {
        if (Score > 10) { 
           // Case 1
        }
    }

    public void DoWork2()
    {
        if (Score < 20) { 
          // Case 2
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM