1

Assuming that we have the following code (which a rather extensive specification of the access conditions) I wanted to refactor it. There's a bunch of such policies very similar to each other, with only a tiny variation in a special claim.

services.AddAuthorization(options =>
{
  options.AddPolicy("ExtensivePolicy_A",
    config => config.RequireClaim("special_claim", "dedicated_value_to_A")
     .RequireClaim("claim1", "value1") ...
  );
  ... 
  options.AddPolicy("ExtensivePolicy_Z",
    config => config.RequireClaim("special_claim", "dedicated_value_to_Z")
     .RequireClaim("claim1", "value1") ...
  );
}

The attempt based on e.g. this, gave me this.

services.AddAuthorization(options =>
{
  options.AddPolicy("ExtensivePolicy_A", ConfigPolicyA);
  ...
  options.AddPolicy("ExtensivePolicy_Z", ConfigPolicyZ);
}

private static void ConfigPolicyA(AuthorizationPolicyBuilder builder) { ... }
...
private static void ConfigPolicyZ(AuthorizationPolicyBuilder builder) { ... }

It's much cleaner but still screams parameterization, as the only difference in the config delegates (actions, funcs whatever they call it), is a tiny detail. Optimally, I'd like my privates to look something along the lines of the following.

private static void ConfigPolicy(AuthorizationPolicyBuilder builder, string special) { ... }

And the call to it would pass a parameter.

options.AddPolicy("MarketingPolicy", ConfigPolicy("a"));

However, I can't get it to work. The compiler complains about the action type being wrong. The original intellisense tells me that I'm supposed to pass something of type Action<AuthorizationPolicyBuilder>, which is kind of against my method's signature (being void). However, it seems to compile whereas the version that returns said type gets the compiler whining about error converting method group to AuthorizationPolicy (which is misleading because that type is a signature of another overloaded method).

My best attempt based on this blog (actions with lambda expression) went as far as this.

private static Action<AuthorizationPolicyBuilder, string> test1
  = builder => { ... };

However, trying to introduce the extra string parameter fails miserably.

private static Action<AuthorizationPolicyBuilder, string> test2 
  = (builder, special) => { ... };

What should I google for to get relevant examples, which I'm sure there are a gazillion of out there? I've found examples on generics and methods as paameters but nothing that tipped me over to aha-side.

5
  • options.AddPolicy("MarketingPolicy", config => ConfigPolicy(config, "a"));? Commented Jul 31, 2021 at 11:08
  • Does this answer your question? C# define function with partial application as delegate Commented Jul 31, 2021 at 11:15
  • @GSerg That might be one way to go. However, I'd like to replace the entire content of the second parameter (i.e. config=>blaha-blaha) and assign it something that I declare below. And I want that something to be parameterized, so that I can pass a string to blaha-blaha but receive the final thingy. Commented Jul 31, 2021 at 11:15
  • @GSerg My last comment was to your first suggestion (not bad, to be honest). As for the second one, it resembles quite a lot the sample I show using definition of Action. That fails in my case due to the extra string passed in (see the edit I just made). A single parameter to the action works as expected, though. Commented Jul 31, 2021 at 11:18
  • @GSerg Are you claiming that I can't exchange (config)=>blah for (config, "fix_value_here")=>blah in C#? I'm comparing to (the principle of) calling a method Hazaa(5) while the signature is void Hazaa(int,string param=""). I was wishing to replace the passed in builder to config and restructure it to be config,"my_fix_value" and then pass it on to my Commented Jul 31, 2021 at 11:28

1 Answer 1

2
private static Action<AuthorizationPolicyBuilder> ConfigBuilderFactory(string param)
{
  return builder => builder
    .RequireClaim("special_claim", param)
    .RequireClaim("claim1", "value1")
    ...;
}
options.AddPolicy("ExtensivePolicy_A", ConfigBuilderFactory("a"));
options.AddPolicy("ExtensivePolicy_Z", ConfigBuilderFactory("z"));
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, this is perfect. I'll take the liberty to change the name of the policy to more generic form that follows the formulation in the original question. I suspect that you picked it up from my comments where I posted the actual production code by quickstake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.