Mohsen Afshin
Mohsen Afshin

Reputation: 13436

Autofac IEnumerable resolve cause multiple construction

I have this registration:

 builder.RegisterAssemblyTypes(assembly)
            .AsClosedTypesOf(typeof(IBusinessRule<>))
            .AsImplementedInterfaces()
            .SingleInstance();

And I resolve it this way:

 using (var scope = Container.BeginLifetimeScope())
 {
        var rules = Container.Resolve<IEnumerable<IBusinessRule<T>>>();

        var result = rules.Select(x => x.IsValid(t));

        if (result.Any(x => !x.Successful))
        {
            var msg = string.Join(Environment.NewLine, result.Where(x => !x.Successful).Select(x => x.Message));

            return new OperationResultBase()
            {
                Message = msg,
                Successful = false,
                Operation = System.Reflection.MethodBase.GetCurrentMethod().Name
            };
        }
        else
        {
            return new OperationResultBase(true);
        }
  }

The problem lies in this line:

var result = rules.Select(x => x.IsValid(t));

With that resolve, the classes that implement the IBusinessRule<T> are called once per each result variable enumeration.

If I call ToList() on result, then everything is OK and would be called only once.

Is calling ToList() a correct approach or the registration has some problems and should be changed?

Upvotes: 0

Views: 515

Answers (1)

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73442

Is calling ToList() a correct approach or the registration has some problems and should be changed?

No, Nothing wrong with your registration. This is the lazy evaluation property of Linq.

In fact it has nothing to do with the autofac. A normal lazy linq query would exactly behave the same way as you see.

If you need the materialized result, you need to call ToList or ToArray. Otherwise, query will be evaluated on each enumeration (for example via foreach);

Upvotes: 3

Related Questions