如何避免Autofac中的隐式集合解析?

时间:2015-05-13 08:03:10

标签: c# asp.net collections autofac resolve

我在ASP.NET中实现MVP模式,我已经定义了如下视图:

public interface IMyView
    {
         IList<User> Users { get; set; }
    }

    public partial class MyPage : Page, IMyView
    {
        public IList<User> Users
        {
            set
            {
                this.grid.DataSource = value;
                this.grid.DataBound();
            }
        }

我的示例页面继承自视图,但每当我访问页面时,Autofac都会向Users属性分配一个默认的空值,而DataBound会抛出异常,因为我的页面还没有完全构建。 如何将Autofac配置为不自动解决? 我现在唯一能做的就是将IList更改为List。

2 个答案:

答案 0 :(得分:1)

最简单的解决方案是修改您的注册,而不是使用此类型的属性注入,这是我推荐的解决方案。

顺便说一下,如果你不能改变注册模式,我可以看到3个解决方案。

  1. 使用状态更改属性的工作方式。

    public MyPage: Page, IMyView
    {
    
      private Boolean _isInitialized; 
    
    
      public void Page_Init(Object sender, EventArgs e)
      {
        this._isInitialized = true; 
      }
    
    
      public IList<User> Users
      {
        get { ... }
        set
        {
          if (this._isInitialized) 
          {
            this.grid.DataSource = value;
            this.grid.DataBound();
          }
        }
      }
    }
    

    肮脏但易于实施。

  2. 实施您自己的PropertiesAutoWiring。您可以使用OnActivating事件来完成此操作。

    ContainerBuilder builder = new ContainerBuilder();
    
    builder.RegisterType<MyPage>().OnActivating(e =>
    {
        foreach (PropertyInfo pi in e.Instance.GetType()
                                                .GetProperties()
                                                .Where(pi => pi.CanWrite))
        {
            if (!pi.PropertyType.IsClosedTypeOf(typeof(IList<>)))
            {
                Object propertyValue = e.Context.ResolveOptional(pi.PropertyType);
                if (propertyValue != null)
                {
                    pi.SetValue(e.Instance, propertyValue);
                }
            }
        }
    });
    

    不要使用此代码,只是为了获得iead。请查看AutowiringPropertyInjector.cs以获得此代码的良好实现。

  3. 删除 Autofac 中的集合支持。集合支持由CollectionRegistrationSource管理。遗憾的是,无法告诉 Autofac 仅删除集合支持,您只能删除所有默认适配器。

    IContainer container = builder.Build(ContainerBuildOptions.ExcludeDefaultModules);
    

    这将删除所有默认模块,即:

    private void RegisterDefaultAdapters(IComponentRegistry componentRegistry)
    {
      this.RegisterGeneric(typeof(KeyedServiceIndex<, >)).As(new Type[]
      {
        typeof(IIndex<, >)
      }).InstancePerLifetimeScope();
      componentRegistry.AddRegistrationSource(new CollectionRegistrationSource());
      componentRegistry.AddRegistrationSource(new OwnedInstanceRegistrationSource());
      componentRegistry.AddRegistrationSource(new MetaRegistrationSource());
      componentRegistry.AddRegistrationSource(new LazyRegistrationSource());
      componentRegistry.AddRegistrationSource(new LazyWithMetadataRegistrationSource());
      componentRegistry.AddRegistrationSource(new StronglyTypedMetaRegistrationSource());
      componentRegistry.AddRegistrationSource(new GeneratedFactoryRegistrationSource());
    }
    
  4. 不幸的是,当使用PropertiesAutoWired()时,无法告诉 Autofac 不要注入特定属性。

答案 1 :(得分:0)

我发现了问题。 感谢您的回答,它帮助我找到了原因。 升级到版本Autofac版本3后,我在web配置中有以下模块:

<add name="PropertyInjection" type="Autofac.Integration.Web.Forms.PropertyInjectionModule, Autofac.Integration.Web" preCondition="managedHandler" />

所以我需要将其删除并替换为以下内容:

 <add
        name="AttributedInjection"
        type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web"
        preCondition="managedHandler" />