简体   繁体   English

将对象的实例传递给以Action <>作为参数的方法

[英]Passing an Instance of an Object to a Method that takes an Action<> as Parameter

In Dot Net Core convention for configuring services is as follows. 在Dot Net Core中,用于配置服务的约定如下。

Method that Requires Action<> As Parameter 需要Action <>作为参数的方法

public static IServiceCollection AddAsResourceServer(this IServiceCollection services, Action<AuthMiddlewareOptions> action = null)
{
     if(action != null)
     {
         AuthMiddlewareOptions authOptions = new AuthMiddlewareOptions();
         action.Invoke(authOptions);
     }
     ...
     return services
}

This allows us to configure our service in startup as follows. 这使我们可以如下配置启动时的服务。

Startup ConfigureServices Method 启动ConfigureServices方法

services.AddAsResourceServer((a) =>
{
    a.Audience = "Long Audience";
    a.Issuer = "provider.com/oauthprovider";
});

This is really cool! 这真是太酷了! I like this pattern. 我喜欢这种模式。 It works very well for allowing anyone to overwrite base configuration options. 它非常适合允许任何人覆盖基本配置选项。

However this seems very cumbersome when you already have an instance of the object. 但是,当您已经有该对象的实例时,这似乎非常麻烦。 How would I create an instance of an object, convert it to an action, and pass that to the .AddAsResourceServer method? 我将如何创建对象的实例,将其转换为动作,然后将其传递给.AddAsResourceServer方法?

I have tried: 我努力了:

Action<AuthMiddleWareOptions> auth = new Action<AuthMiddleWareOptions>()
/// The above way still requires a "target" in constructor so it doesnt work.
///so i still need to pass each 
///property into it.

My consumers of the service may have just created an instance of AuthMiddleWareOptions and populated through appsettings! 我的服务使用者可能刚刚创建了AuthMiddleWareOptions实例,并通过appsettings进行填充!

They may have done something like this. 他们可能做了这样的事情。

AuthMiddlewareOptions myoptions = new AuthMddlewareOptions();
Configuration.Bind("AuthMiddlewareOptions", myoptions);

Now that they have 'myoptions'. 现在他们有了“ myoptions”。 Is there a quick way to use that with the Action Parameter. 有没有一种快速的方法可以将其与Action Parameter一起使用。 Maybe like this? 也许是这样吗?

AuthMiddlewareOptions myoptions = new AuthMddlewareOptions();
Configuration.Bind("AuthMiddlewareOptions", myoptions);
services.AddAsResourceServer((a) => SpecialThing(myoptions));

You can simply bind your configuration to the options instance provided by the method. 您可以简单地将配置绑定到该方法提供的选项实例。

services.AddAsResourceServer(options => 
{
    Configuration.Bind("AuthMiddlewareOptions", options);
});

You may register multiple configuration delegates for a single option class: 您可以为一个选项类注册多个配置委托:

services.Configure<AuthMiddlewareOptions>(Configuration.GetSection("AuthMiddlewareOptions"));

services.AddAsResourceServer(options => SpecialThing(options));

And AddAsResourceServer should call services.Configure , as well: 并且AddAsResourceServer也应该调用services.Configure

public static IServiceCollection AddAsResourceServer(this IServiceCollection services, Action<AuthMiddlewareOptions> action = null)
{
    if (action != null)
        services.Configure(action);


    // ...

    return services;
}

Having this setup, AuthMiddlewareOptions is populated from the configuration section "AuthMiddlewareOptions", then the customization delegate ( SpecialThing ) has a chance to change the options filled at the previous step. 有了这个设置,AuthMiddlewareOptions从配置节“AuthMiddlewareOptions”填充,然后定制委托(SpecialThing)有机会改变填充在上一步骤的选项。

It's important that the order matters ! 顺序很重要 If you swap the two lines, SpecialThing 's changes will be overwritten by the values coming from the configuration. 如果交换两行,则SpecialThing的更改将被来自配置的值覆盖。

You need to do it the other way arround. 您需要以其他方式进行操作。

I use for example the AddAuthorization since I do not find your method: 我使用例如AddAuthorization因为找不到您的方法:

services.AddAuthorization(c =>
{
    c.DefaultPolicy = null;
});

This can be configured using the following method: 可以使用以下方法进行配置:

public static void Config(AuthorizationOptions configure, IConfiguration configuration)
{
    configure.DefaultPolicy = null;
    //Configuration.Bind("AuthMiddlewareOptions", myoptions);
}

That way you can do: 这样,您可以:

services.AddAuthorization(c => Config(c, Configuration));

The problem is, that in these Action<T> methods you get the object T , which is already instantiated. 问题在于,在这些Action<T>方法中,您获得了已实例化的对象T So you need to copy the custom created object to it. 因此,您需要将自定义创建的对象复制到该对象。 With above we change the API, so it is configured on the correct object. 通过上面的内容,我们更改了API,因此将其配置在正确的对象上。

I tried many patterns, it wasn't until I hovered over a in the method to realize that it wasnt of type Action<AuthMiddlewareOptions> , but it was in fact AuthMiddleWareOptions . 我尝试了许多图案,但直到我悬停a在该方法中认识到,它不是类型的Action<AuthMiddlewareOptions>但它实际上AuthMiddleWareOptions so this very simple assignment worked! 所以这个非常简单的作业就可以了!

services.AddAsResourceServer(a => a = myoptions);

Quick answer to your question "Passing an Instance of an Object to a Method that takes an Action<> as Parameter" is "no, you can't" 您的问题“将对象的实例传递给以Action <>作为参数的方法的问题”的快速答案是“不,您不能”

But as a workaround, you could simply make a deepclone of your object, to swap the properties of the "inner" options. 但是,作为一种解决方法,您可以简单地对对象进行深层克隆,以交换“内部”选项的属性。

Something like this : 像这样的东西:

static class Copy
{
    public static void ObjectToAnother<T>(T source, T target)
    {
        foreach (var sourceProp in source.GetType().GetProperties())
        {
            var targetProp = target.GetType().GetProperty(sourceProp.Name);
            targetProp.SetValue(target, sourceProp.GetValue(source, null), null);
        }
    }
}

And you could use that like this : 您可以这样使用:

var obj = new Obj();
Foo.Bar((a) =>
{
    Copy.ObjectToAnother(a, obj);
});

It should work 它应该工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将参数传递给 Action 方法 - Passing a parameter to Action method 在以方法为参数的方法中传递字符串 - Passing a string in a method that takes a method as its parameter 将 Action 作为参数传递给方法并实例化 - Pass and instance to a method with Action as parameter CRUD操作,EntityFramework:将TextBox值(文本)传递给以类对象为参数的方法 - CRUD operation, EntityFramework: Passing TextBox value(Text) to a method that takes class object as parameter 将对象从 F# 传递到将其作为输出参数的 C# 方法不起作用? - Passing an object from F# into a C# method which takes it as an out parameter doesn't work? 将带有&符号的参数传递给控制器​​操作方法 - Passing a parameter with an ampersand to a controller action method 将 class 的实例作为参数传递给 Url.Action 的操作/方法 - Passing an instance of a class as an argument to the action/method of Url.Action C#为什么将一个类实例传递给一个接受对象作为参数并将其装回工作的方法 - C# Why does passing of an class instance to a method which accepts object as parameter and boxing it back work 如何激活将操作作为其参数的泛型方法 - How to activate a generic method that takes an action as its parameter 参数传递给方法以删除对象创建 - Parameter passing to method to remove object creation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM