Reputation: 195
I'm implementing MVP pattern in ASP.NET and I have defined a view like below:
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();
}
}
My sample page inherits from the view but whenever I visit the page Autofac assigns a default empty value to Users property and DataBound throws an exception because my page is not built completely yet. How can I configure Autofac to not to resolve it automatically? The only thing I can do now is to change IList to List.
Upvotes: 1
Views: 416
Reputation: 16192
The easiest solution would be to modify your registration and not to use property injection for this type, this is the solution I recommend.
By the way, if you can't change the registration mode, I can see 3 solutions.
Change the way the property works by using a state.
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();
}
}
}
}
Dirty but simple to implement.
Implement your own PropertiesAutoWiring
. You can do so by using the OnActivating event.
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);
}
}
}
});
Don't use this code, it is just to get you the iead. Look at AutowiringPropertyInjector.cs for a good implementation of this code.
Remove the collection support in Autofac. Collection support is managed by the CollectionRegistrationSource
. Unfortunately There is no way to tell Autofac to remove only the collection support, you can only remove all default adapters.
IContainer container = builder.Build(ContainerBuildOptions.ExcludeDefaultModules);
This will remove all default modules, ie :
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());
}
Unfortunately, when PropertiesAutoWired()
is used, there is no way to tell Autofac not to inject a specific property.
Upvotes: 1
Reputation: 195
I found the problem. Thanks to your answer it helped me to find the cause. After upgrading to version Autofac version 3 I have following module in web config:
<add name="PropertyInjection" type="Autofac.Integration.Web.Forms.PropertyInjectionModule, Autofac.Integration.Web" preCondition="managedHandler" />
So I need to remove it and replace it with following:
<add
name="AttributedInjection"
type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web"
preCondition="managedHandler" />
Upvotes: 0