Git Product home page Git Product logo

autofac.extras.aggregateservice's Introduction

Autofac character Autofac logo

Autofac is an IoC container for Microsoft .NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating regular .NET classes as components.

Build status codecov NuGet

Autofac on Stack Overflow Join the chat at https://gitter.im/autofac/autofac

Get Packages

You can get Autofac by grabbing the latest NuGet package. There are several application integration and extended functionality packages to choose from. If you're feeling adventurous, continuous integration builds are on MyGet.

Release notes are available on GitHub.

Get Help

Need help with Autofac? We have a documentation site as well as API documentation. We're ready to answer your questions on Stack Overflow or check out the discussion forum.

Get Started

Our Getting Started tutorial walks you through integrating Autofac with a simple application and gives you some starting points for learning more.

Super-duper quick start:

Register components with a ContainerBuilder and then build the component container.

var builder = new ContainerBuilder();

builder.Register(c => new TaskController(c.Resolve<ITaskRepository>()));
builder.RegisterType<TaskController>();
builder.RegisterInstance(new TaskController());
builder.RegisterAssemblyTypes(controllerAssembly);

var container = builder.Build();

Resolve services from a lifetime scope - either the container or a nested scope:

var taskController = container.Resolve<TaskController>();

There is a growing number of application integration libraries that make using Autofac with your application a snap. Support for several popular frameworks is also available through the "Extras" packages.

Intrigued? Check out our Getting Started walkthrough!

Project

Autofac is licensed under the MIT license, so you can comfortably use it in commercial applications (we still love contributions though).

File issues in the repo with the associated feature/code.

Sponsors

Autofac is supported by AWS. Thanks for your contribution!

Contributing / Pull Requests

Refer to the Contributor Guide for setting up and building Autofac source.

You can also open this repository right now in VS Code.

autofac.extras.aggregateservice's People

Contributors

alexmg avatar alistairjevans avatar alsami avatar shiftkey avatar tillig avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

autofac.extras.aggregateservice's Issues

Resolve aggregate services using keyed registrations

I have an aggregate service containing interfaces that are only registered with keys (using Keyed<>()). Furthermore, each interface within the aggregate has the same number of concrete implementations, which are all mapped to the same key. Essentially it's a non-jagged 2D array of registrations.

I'd like the ability to resolve the aggregate service with IIndex, which would forward the key to the resolution of the services within it.

I have an example that demonstrates the behavior I'm looking for, which I'll provide below.

internal interface IMyService2
{
    void PrintInfo();
}

internal interface IMyService1
{
    void PrintInfo();
}

internal class MyService1Impl1 : IMyService1
{
    public void PrintInfo()
    {
        Console.WriteLine(" - MyService1Impl1");
    }
}

internal class MyService1Impl2 : IMyService1
{
    public void PrintInfo()
    {
        Console.WriteLine(" - MyService1Impl2");
    }
}

internal class MyService2Impl1 : IMyService2
{
    public void PrintInfo()
    {
        Console.WriteLine(" - MyService2Impl1");
    }
}

internal class MyService2Impl2 : IMyService2
{
    public void PrintInfo()
    {
        Console.WriteLine(" - MyService2Impl2");
    }
}

internal interface IMyAggregateServices
{
    public IMyService1 Service1 { get; init; }
    public IMyService2 Service2 { get; init; }
}

public static class Program
{
    public static void Main()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<MyService1Impl1>().Keyed<IMyService1>("one");
        builder.RegisterType<MyService1Impl2>().Keyed<IMyService1>("one");
        builder.RegisterType<MyService2Impl1>().Keyed<IMyService2>("two");
        builder.RegisterType<MyService2Impl2>().Keyed<IMyService2>("two");
        builder.RegisterAggregateService<IMyAggregateServices>();

        var container = builder.Build();

        var index = container.Resolve<IIndex<string, IMyAggregateServices>>();
        var aggregateServices = index["one"];

        Console.WriteLine("Print Service1:");
        aggregateServices.Service1.PrintInfo();

        Console.WriteLine("Print Service2:");
        aggregateServices.Service2.PrintInfo();
    }
}

Above, I expect the following output:

Print Service1:
 - MyService1Impl1
Print Service2:
 - MyService2Impl1

Obviously, the code above won't even execute. Instead, I get this exception:

Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'one (ConsoleApp1.IMyAggregateServices)' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

If there's a reasonable workaround, I'm open to that as well. I'm sure I could implement my own concrete aggregate class to simulate this somehow, but I was hoping native support for this would be added.

Unexpected Behavior with Generic Parameters

I'm not sure if this is working as designed or not, but it is something that caught me off guard. Please feel free to correct any misconceptions I may have about how the library should work.

Describe the Bug

When a method on the aggregate services interface accepts a generic parameter, a new instance of the parameter is created (or is attempted to) when invoking the method rather than using the parameter that is given to it.

Steps to Reproduce

I added a new pass-through interface and implementation

    public interface IPassThroughOpenGeneric<T>
    {
        IOpenGeneric<T> OpenGeneric { get; }
    }

    public class OpenGenericPassThroughImpl<T> : IPassThroughOpenGeneric<T>
    {
        public OpenGenericPassThroughImpl(IOpenGeneric<T> openGeneric)
        {
            OpenGeneric = openGeneric;
        }

        public IOpenGeneric<T> OpenGeneric { get; }
    }

and added this method to IOpenGenericAggregate

        IPassThroughOpenGeneric<T> PassThroughOpenGeneric<T>(IOpenGeneric<T> openGeneric);

In AggregateServiceGenericsFixture, I added this registration

    builder.RegisterGeneric(typeof(OpenGenericPassThroughImpl<>))
        .As(typeof(IPassThroughOpenGeneric<>));

then this test

        [Fact]
        public void Method_UnpackOpenGeneric()
        {
            var aggregateService = _container.Resolve<IOpenGenericAggregate>();

            var generic = aggregateService.GetOpenGeneric<It.IsAnyType>();

// -----works as expected-----
            var passThroughFunc = _container.Resolve<Func<IOpenGeneric<It.IsAnyType>, IPassThroughOpenGeneric<It.IsAnyType>>>();
            var genericFromPassThroughFunc = passThroughFunc(generic);
//----------
            Assert.Same(generic, genericFromPassThroughFunc.OpenGeneric);
        }

However, if I use the aggregate service instead, it does not work.

        [Fact]
        public void Method_UnpackOpenGeneric()
        {
            var aggregateService = _container.Resolve<IOpenGenericAggregate>();

            var generic = aggregateService.GetOpenGeneric<It.IsAnyType>();

// -----does not work-----
            var genericPassThrough = aggregateService.PassThroughOpenGeneric(generic);
//----------
            Assert.Same(generic, genericPassThrough.OpenGeneric);
        }

Expected Behavior

I am under the impression that the aggregate service should behave as the Func<> does. Here is my example if you like to see my full implementation:
GenericParameterExample.zip

Dependency Versions

Autofac: v6.0.0

Autofac 4 update problem

Hi,

after upgrading to Autofac 4.1 following exception is raised:

OneTimeSetUp: System.IO.FileLoadException : Could not load file or assembly 'Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  ----> System.IO.FileLoadException : Could not load file or assembly 'Autofac, Version=3.3.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
  Exception doesn't have a stacktrace

I have binding redirect redirecting to 3.5.0.0 version:

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
    </assemblyBinding>

FusionLog:

=== Pre-bind state information ===
LOG: DisplayName = Autofac, Version=3.3.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da
 (Fully-specified)
LOG: Appbase = file:///D:/repo/bin/Debug
LOG: Initial PrivatePath = NULL
Calling assembly : Autofac.Extras.AggregateService, Version=4.0.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\repo\bin\Debug\Database.Tests.dll.config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 3.3.0.0 redirected to 3.5.0.0.
LOG: Post-policy reference: Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da
LOG: Attempting download of new URL file:///D:/repo/bin/Debug/Autofac.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

Assemblies without Autofac.Extras.AggregateService works. Changing redirect to:

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
    </assemblyBinding>

only breaks different things.

Build-time aggregated service generation

As stated in documentation, there is a small but non-zero amount of overhead on each method call.
Have you considered the option to generate the aggregated service implementation during build time, using Roslyn for example ?

Open Generic Support

Does This Supported?

`

public class PermissionBusiness : BusinessBaseEx<Permission, IPermissionRepository>, IPermissionBusiness
{

    public PermissionBusiness(IBusinessService<IPermissionRepository> aggregateService) : base(aggregateService)
    {
    }

}

builder.RegisterAggregateService(typeof(IBusinessService<>));
builder.RegisterAggregateService<IInfrastructureService>();


public interface IInfrastructureService
{
    IMapper Mapper { get; set; }
    IEventBus EventBus { get; set; }
    ICacheService CacheService { get; set; }
}

public interface IBusinessService<TRepository> : IInfrastructureService
{
    TRepository Repository { get; set; }
}

`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.