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

时间:2018-08-22 20:27:48

标签: c# asp.net-core asp.net-core-2.0

在Dot Net Core中用于配置服务的约定如下。

  

需要操作<>作为参数的方法

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

这使我们可以按照以下步骤在启动时配置服务。

  

启动ConfigureServices方法

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

这真的很酷!我喜欢这种模式。它非常适合允许任何人覆盖基本配置选项。

但是,当您已经有该对象的实例时,这似乎非常麻烦。我将如何创建对象的实例,将其转换为动作,并将其传递给.AddAsResourceServer方法?

  

我尝试过:

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.

我的服务使用者可能刚刚创建了AuthMiddleWareOptions实例,并通过appsettings进行填充!

  

他们可能已经做了类似的事情。

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

现在它们具有“ myoptions”。有没有一种快速的方法可以将其与Action Parameter一起使用。也许是这样吗?

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

5 个答案:

答案 0 :(得分:2)

您只需将您的配置绑定到方法提供的选项实例。

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

答案 1 :(得分:1)

您可以为一个选项类注册多个配置委托:

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

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

并且 AddAsResourceServer 也应该调用services.Configure

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


    // ...

    return services;
}

具有此设置,从配置部分“ AuthMiddlewareOptions”填充 AuthMiddlewareOptions ,然后自定义委托( Specialthing )可以更改前一个填充的选项。步骤。

顺序很重要很重要!如果交换两行,则 SpecialThing 的更改将被来自配置的值覆盖。

答案 2 :(得分:0)

您需要以其他方式进行操作。

例如,由于找不到您的方法,我使用了AddAuthorization

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

可以使用以下方法进行配置:

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

您可以这样做:

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

问题是,在这些Action<T>方法中,您获得了已实例化的对象T。因此,您需要将自定义创建的对象复制到该对象。通过上面的操作,我们更改了API,因此将其配置在正确的对象上。

答案 3 :(得分:-1)

我尝试了许多模式,直到我将鼠标悬停在方法中的a上才意识到它不是Action<AuthMiddlewareOptions>类型,但实际上是AuthMiddleWareOptions。所以这个非常简单的任务就可以了!

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

答案 4 :(得分:-1)

您的问题“将对象的实例传递给以Action <>作为参数的方法”的快速答案是“不,您不能”

但是,作为解决方法,您可以简单地对对象进行深层克隆,以交换“内部”选项的属性。

类似这样的东西:

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);
        }
    }
}

您可以这样使用:

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

应该可以