I'm using Autofac 2.4.4.705.
The output of the following code is: 1 (which means the resolved collection contains one item. I thought it should be empty)
class Program
{
static void Main(string[] args)
{
var builder = new Autofac.ContainerBuilder();
builder.RegisterModule(new AutofacModule());
using (var container = builder.Build())
{
开发者_如何学运维 var x = container.Resolve<ObservableCollection<A>>();
Console.WriteLine(x.Count);
}
}
}
class A
{
}
class AutofacModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof(ObservableCollection<>))
.As(typeof(ObservableCollection<>));
}
}
It seems the issue is cause by:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
If I remove it from AutofacModule, then the output is 0.
Any ideas?
Thanks
Update:
Ah, I think I understand now. Autofac thought I want to resolve all types of A, and there is one type of A in this example (A itself), so the ObservableCollection contains one item. I previously thought only IEnumerable<> has this behavior. But it seems subtypes of IEnumerable<> also have this behavior.
But sometimes what I really want is to inject an collection, for example, sometime I need to inject DispacherNotifiedObservableCollection into my ViewModels. Any workarounds?
Update 2:
Based on the answer of Nicholas Blumhardt, I changed my code to:
builder.RegisterGeneric(typeof(ExtendedObservableCollection<>))
.As(typeof(IObservableCollection<>))
.UsingConstructor();
public interface IObservableCollection<T> :
IList<T>, ICollection<T>, IEnumerable<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
void AddRange(IEnumerable<T> list);
void Sort<TKey>(Func<T, TKey> keySelector, System.ComponentModel.ListSortDirection direction);
void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer);
}
Now everything works fine. Thanks!
The behavior you're seeing is a result of the ObservableCollection type having a constructor that accepts IEnumerable.
You can change this to use the default constructor using the UsingConstructor() option.
ObservableCollection itself might not be a very good contract to depend on though- it is a bit unclear what the semantics should generally be. Wrapping it in a specialized component with it's own interface is the better option.
精彩评论