加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

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

发布时间:2020-12-16 09:19:06 所属栏目:asp.Net 来源:网络整理
导读:我一直在寻找WebApi属性的非参数注入选项. 我的问题是使用Structuremap是否真的可以实现这一点? 我一直在谷歌搜索,但继续提出属性注入(我不喜欢使用)或假设的构造函数注入的实现,我到目前为止无法复制. 我选择的容器是Structuremap,但是任何这样的例子就足
我一直在寻找WebApi属性的非参数注入选项.

我的问题是使用Structuremap是否真的可以实现这一点?

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

我选择的容器是Structuremap,但是任何这样的例子就足够了,因为我能够转换它.

有人管过这个吗?

解决方法

对的,这是可能的.你(和大多数人一样)被微软的动作过滤器属性的营销抛出,它们被方便地放入一个单独的类中,但根本不是DI友好的.

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

>一个不包含用于标记控制器和操作方法的行为的属性.
> DI友好类,实现IActionFilter并包含所需的行为.

方法是使用IActionFilter测试属性的存在,然后执行所需的行为.可以为动作过滤器提供所有依赖项(通过构造函数),然后在组合应用程序时注入.

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 07002.

要使用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; }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读