开发者

Autofac: Injected collection is not empty (contains one item)

开发者 https://www.devze.com 2023-02-15 11:10 出处:网络
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)

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号