gpt4 book ai didi

asp.net-web-api - 构造函数依赖注入(inject) WebApi 属性

转载 作者:行者123 更新时间:2023-12-03 18:10:29 25 4
gpt4 key购买 nike

我一直在寻找 WebApi 属性的非参数注入(inject)选项。

我的问题很简单,这是否真的可以使用 Structuremap?

我一直在谷歌搜索,但不断提出属性注入(inject)(我不喜欢使用)或构造函数注入(inject)的假设实现,到目前为止我无法复制。

我选择的容器是 Structuremap,但是任何示例都足够了,因为我能够转换它。

有人管理过这个吗?

最佳答案

是的,有可能。你(和大多数人一样)被微软的 Action 过滤器属性营销所吸引,这些属性被方便地放入一个类中,但对 DI 一点也不友好。

解决方案是将 Action 过滤器属性分成两部分as demonstrated in this post :

  • 一个不包含任何行为来标记您的 Controller 和操作方法的属性。
  • 一个实现 IActionFilter 的 DI 友好类并包含所需的行为。

  • 方法是使用 IActionFilter 来测试属性是否存在,然后执行所需的行为。 Action 过滤器可以提供所有依赖项(通过构造函数),然后在组合应用程序时注入(inject)。
    IConfigProvider provider = new WebConfigProvider();
    IActionFilter filter = new MaxLengthActionFilter(provider);
    config.Filters.Add(filter);

    NOTE: If you need any of the filter's dependencies to have a lifetime shorter than singleton, you will need to use a GlobalFilterProvider as in this answer.



    要将其与 StructureMap 连接起来,您需要从 DI 配置模块返回一个容器实例。 Application_Start 方法仍然是组合根的一部分,因此您可以在此方法中的任何位置使用容器,它仍然不被视为服务定位器模式。请注意,我没有在此处显示完整的 WebApi 设置,因为我假设您已经使用 WebApi 进行了有效的 DI 配置。如果你需要一个,那是另一个问题。
    public class DIConfig()
    {
    public static IContainer Register()
    {
    // Create the DI container
    var container = new Container();

    // Setup configuration of DI
    container.Configure(r => r.AddRegistry<SomeRegistry>());
    // Add additional registries here...

    #if DEBUG
    container.AssertConfigurationIsValid();
    #endif

    // Return our DI container instance to the composition root
    return container;
    }
    }

    public class MvcApplication : System.Web.HttpApplication
    {
    protected void Application_Start()
    {
    // Hang on to the container instance so you can resolve
    // instances while still in the composition root
    IContainer container = DIConfig.Register();

    AreaRegistration.RegisterAllAreas();

    // Pass the container so we can resolve our IActionFilter
    WebApiConfig.Register(GlobalConfiguration.Configuration, container);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    AuthConfig.RegisterAuth();
    }
    }

    public static class WebApiConfig
    {
    // Add a parameter for IContainer
    public static void Register(HttpConfiguration config, IContainer container)
    {
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );

    // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
    // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
    // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
    //config.EnableQuerySupport();

    // Add our action filter
    config.Filters.Add(container.GetInstance<IMaxLengthActionFilter>());
    // Add additional filters here that look for other attributes...
    }
    }

    MaxLengthActionFilter 的实现看起来像这样:
    // Used to uniquely identify the filter in StructureMap
    public interface IMaxLengthActionFilter : System.Web.Http.Filters.IActionFilter
    {
    }

    public class MaxLengthActionFitler : IMaxLengthActionFilter
    {
    public readonly IConfigProvider configProvider;

    public MaxLengthActionFilter(IConfigProvider configProvider)
    {
    if (configProvider == null)
    throw new ArgumentNullException("configProvider");
    this.configProvider = configProvider;
    }

    public Task<HttpResponseMessage> ExecuteActionFilterAsync(
    HttpActionContext actionContext,
    CancellationToken cancellationToken,
    Func<Task<HttpResponseMessage>> continuation)
    {
    var attribute = this.GetMaxLengthAttribute(filterContext.ActionDescriptor);
    if (attribute != null)
    {
    var maxLength = attribute.MaxLength;
    // Execute your behavior here (before the continuation),
    // and use the configProvider as needed

    return continuation().ContinueWith(t =>
    {
    // Execute your behavior here (after the continuation),
    // and use the configProvider as needed

    return t.Result;
    });
    }
    return continuation();
    }

    public bool AllowMultiple
    {
    get { return true; }
    }

    public MaxLengthAttribute GetMaxLengthAttribute(ActionDescriptor actionDescriptor)
    {
    MaxLengthAttribute result = null;

    // Check if the attribute exists on the action method
    result = (MaxLengthAttribute)actionDescriptor
    .GetCustomAttributes(typeof(MaxLengthAttribute), false)
    .SingleOrDefault();

    if (result != null)
    {
    return result;
    }

    // Check if the attribute exists on the controller
    result = (MaxLengthAttribute)actionDescriptor
    .ControllerDescriptor
    .GetCustomAttributes(typeof(MaxLengthAttribute), false)
    .SingleOrDefault();

    return result;
    }
    }

    而且,不应包含任何行为的属性应如下所示:
    // This attribute should contain no behavior. No behavior, nothing needs to be injected.
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
    public class MaxLengthAttribute : Attribute
    {
    public MaxLengthAttribute(int maxLength)
    {
    this.MaxLength = maxLength;
    }

    public int MaxLength { get; private set; }
    }

    关于asp.net-web-api - 构造函数依赖注入(inject) WebApi 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28352680/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com