Giter Club home page Giter Club logo

autofac.servicefabric'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.servicefabric's People

Contributors

alexmg avatar alexperovich avatar alistairjevans avatar alsami avatar pcherpitel avatar pvivera avatar tidusjar avatar tillig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autofac.servicefabric's Issues

ServiceFabric package requires Autofac 4.6

Hello,

I installed the latest nuget package (1.0.0-beta2) and when attempting to use the RegisterServiceFabricSupport extension method I am getting the following:

Assembly 'Autofac.Integration.ServiceFabric' with identity 'Autofac.Integration.ServiceFabric, Version=1.0.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da' uses 'Autofac, Version=4.6.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da' which has a higher version than referenced assembly 'Autofac' with identity 'Autofac, Version=4.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da'

Looking at the package it takes in the Autofac 4.5.0 package and not 4.6.X.
After installing 4.6.1 it now compiles correctly.

ServiceContext

What one almost always needs injected into other components in a Service Fabric application is ServiceContext (StarefulServiceContext, StatelessServiceContext) which is passed to the Service Fabric service constructor. What I have done in the past is to take a Lazy dependency in other implementation classes, and populate a program scoped instance variable with the context like this:

builder
    .RegisterStatelessService<MyService>("MyServiceType")
    .OnActivated(args => Context = args.Instance.Context);
builder
    .Register(c => Context)
    .As<StatelessServiceContext>()
    .As<ServiceContext>()
    .InstancePerLifetimeScope();

where Context is the program scoped instance variable.

It would be nice if Autofac.ServiceFabric did this itself, possibly with keyed dependencies.

Message "Access is denied

Hi,

My stateless service is Internal. I have added the following on top of my namespace:
[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
However, I get following error message:
Message "Access is denied: 'xxx" string

I do not want to make my classes public. I would like to follow C# convention and make them Internal as I'm supposed to.

Thanks,
Marty

Allow use of current ILifetimeScope in the exception callback

Great to see the addition of the constructorExceptionCallback in release 2.1.0. I need to be able to resolve my logger instance in the callback. Is it possible to change the callback signature from Action<Exception> to Action<IComponentContext, Exception>?

Publish nuget package with support of Service Fabric > 3.0.0

We cannot upgrade to the latest Service Fabric packages, because we get the following error:

Unable to resolve dependencies. 'Microsoft.ServiceFabric.Actors 3.0.456' is not compatible with 'Autofac.ServiceFabric 1.1.0 constraint: Microsoft.ServiceFabric.Actors (>= 2.4.164 && < 3.0.0)'.

Unable to resolve ServiceContext for dependent component

Thanks for coming up with solution to do dependency injection, but facing an issue while trying to resolve to service context to dependent class,
While doing an exercise, I created a stateless service ,
like

 public Stateless1(StatelessServiceContext context, IConfigSettingsProvider configSettingsProvider)
{
//
}

 IConfigSettingsProvider
{
ConfigSettingsProvider(StatefulServiceContext context);
ConfigSettingsProvider(StatelessServiceContext context)
}

Program.cs

                 var builder = new ContainerBuilder();

                builder.Register(ctx =>
                {
                    var context = ctx.Resolve<StatelessServiceContext>();
                    return new ConfigSettingsProvider(context);

                }).As<IConfigSettingsProvider>().SingleInstance();


Exception:

Autofac.Core.Registration.ComponentNotRegisteredException was unhandled by user code
  HResult=-2146233088
  Message=The requested service 'System.Fabric.StatelessServiceContext' 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.
  Source=Autofac
  StackTrace:
       at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
       at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)
       at Stateless1.Program.<>c.<Main>b__0_0(IComponentContext ctx) in C:\WorkingFolder\Spike\DITesting\Stateless1\Program.cs:line 22
       at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass0_0`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)
       at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
       at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
  InnerException: 

I understand the problem here but How do I resolve the context?

Cannot create Stateless Service in Service Fabric injecting my own objects in

Hello

I have a Stateless service which cannot be created

        public ServiceFabric(StatelessServiceContext context,
            ServiceLoggerFactory serviceLoggerFactory, ServiceConfiguration configuration,
            ITrayportApiService trayportApiService)
            : base(context)
        {
//My Code here
}

I have used breakpoints and verified that ITrayportApiService is known about and is registered

Can someone help urgently please?

The code we use to create the container is below where UseAzureWireUp is true

        public static IContainer GetContainer<TServiceFabric>(string serviceFabricType, bool log = false)
            where TServiceFabric : StatelessService
        {
            if (_container == null)
            {
                var builder = new ContainerBuilder();

                try
                {
                    var moduleTypes = TypeCache.GetTypes(x => x.IsClassEx() && !x.IsAbstractEx() && x.ImplementsInterfaceEx<IModule>());

                    if (log)
                        Debug.WriteLine($"NEED TO LOG {serviceFabricType}" );


                    foreach (var moduleType in moduleTypes)
                    {
                        var module = Activator.CreateInstance(moduleType) as IModule;
                        if (module != null)
                        {
                            if (log)
                                Debug.WriteLine($"{serviceFabricType} {moduleType.Name}");

                            builder.RegisterModule(module);
                        }
                    }



                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                    throw;
                }
                if (UseAzureWireup)
                {
                    builder.RegisterServiceFabricSupport();

                    // This needs to match the name of the type in 
                    // PackageRoot\ServiceManifest.xml AND ApplicationPackageRoot\ApplicationManifest
                    builder.RegisterStatelessService<TServiceFabric>(serviceFabricType);
                }

                var container = builder.Build();

                // To make sure the logger is being instantiated, resolve it
                var logger = container.Resolve<ILogger>();

                _container = container;
            }

            return _container;
        }

Paul

The message is below

I cant get the inner exception details which is annoying!

Unhealthy event: SourceId='System.RA', Property='ReplicaOpenStatus', HealthState='Warning', ConsiderWarningAsError=false.
Replica had multiple failures during open on _Node_0. API call: IStatelessServiceInstance.Open(); Error = Autofac.Core.DependencyResolutionException (-2146233088)
An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = ServiceFabricProxy (DelegateActivator), Services = [Inspired.TradingPlatform.TrayportApi.Primary.ServiceFabric.ServiceFabric], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner except
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters)
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable1 parameters)
at Autofac.Integration.ServiceFabric.StatelessServiceFactoryRegistration.<>c__DisplayClass0_01.b__0(StatelessServiceContext context) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceFactory.System.Fabric.IStatelessServiceFactory.CreateInstance(String serviceTypeName, Uri serviceName, Byte[] initializationData, Guid partitionId, Int64 instanceId) at System.Fabric.ServiceFactoryBroker.<>c__DisplayClass9_0.b__0(IStatelessServiceFactory factory, ServiceInitializationParameters initParams) at System.Fabric.ServiceFactoryBroker.CreateHelper[TFactory,TReturnValue](IntPtr nativeServiceType, IntPtr nativeServiceName, UInt32 initializationDataLength, IntPtr nativeInitializationData, Guid partitionId, Func3 creationFunc, Action`2 initializationFunc, ServiceInitializationParameters initializationParameters)
For more information see: http://aka.ms/sfhealth

There is a plan to sign the assembly?

In order to use the library we had to remove the digital signature from our services, do you have plan to add the digital signature to the library?

Allow injecting additional registrations during the creation of service lifetimescope

Problem Statement

Service registration is closed for extension and makes injecting additional dependencies within the SF service lifetime scope impossible. There is a challenge with proper initializing the Application Insights with Autofac. Based on AI for SF docu (https://github.com/microsoft/ApplicationInsights-ServiceFabric) there is a requirement to register FabricTelemetryInitializerExtension.CreateFabricTelemetryInitializer(ServiceContext) as a ITelemetryInitializer. However, this must be done while creating the lifetimescope in RegisterServiceAsync method. Otherwise, we don't have ServiceContext available.

Desired Solution

This can be easily achieved by adding additional parameter of type Action to RegisterStatefulServiceFactory/RegisterStatelessServiceFactory/RegisterActorFactory methods and make sure the parameter is passed from AutofacServiceExtensions class methods. Then in factory methods we can add custom dependencies in Begin scope action

var lifetimeScope = container.BeginLifetimeScope(tag, builder =>
                {
                    builder.RegisterInstance(context)
                        .As<StatefulServiceContext>()
                        .As<ServiceContext>();

                    customRegistrations?.Invoke(builder);
                });

Then we could register service with following code:

                Action<ContainerBuilder> configure = b =>
                {
                    AppInsightsSupportInjectAction(b);

                    b.RegisterInstance(new StateManagerHolder());
                    b.Register(ctx => ctx.Resolve<StateManagerHolder>().StateManager ?? new ReliableStateManager(resolve(ctx)))
                        .As<IReliableStateManager>().InstancePerDependency();
                };

                try
                {
                    containerBuilder.RegisterStatefulService<TService>(serviceTypeName, serviceTypeName, configure => configure.Register(ctx => FabricTelemetryInitializerExtension.CreateFabricTelemetryInitializer(ctx.Resolve<ServiceContext>()))

Alternatives You've Considered

I haven't found any workaround to initialize the SF telemetry initializer in the scope created for SF service. I cannot do it in the Kestrel Webhost, as I have remoting methods (my service implements the SF's IService interface).

Additional Context

In my solution, I use a mix of HostBulder with Autofac along with Autofac SF integration so
registering FabricTelemetryInitializer out of service scope ends with exception as serviceContext is not resolved during the Build operation on HostBuilder. The reason for that is the AI integration which needs to resolve ILogger thus it pulls for all ITelemetryInitializers as well.

Additional benefit is that we could also register the IReliableStateManager. Now it's not possible because state manager is properly created withing the StatefulService and lifetime scope registration is being done befor. However with some helper class:

public class StateManagerHolder
    {
        /// <summary>
        /// Gets or sets the state manager.
        /// </summary>
        public IReliableStateManager StateManager { get; set; }
    }

we can inject additional registration

Action<ContainerBuilder> configure = b =>
                {
                    b.RegisterInstance(new StateManagerHolder());
                    b.Register(ctx => ctx.Resolve<StateManagerHolder>().StateManager ?? new ReliableStateManager(resolve(ctx)))
                        .As<IReliableStateManager>().InstancePerDependency();
                };

and make sure we update reference StateManager in RunAsync as follows:

            var holder = this.rootScope.Resolve<StateManagerHolder>();
            if (holder.StateManager == null)
            {
                holder.StateManager = this.StateManager;
            }

the last step is required as for some reason new ReliableStateManager(resolve(ctx)) doesn't create valid reliable manager object - at least in my case injected stateful context in ctor is not assigned properly.

How to inject custom ActorService

Hi! I'm trying to use autofac to register custom actor services like I do with this code:

ActorRuntime.RegisterActorAsync<StartupAgent>((context, actorType) => new StartupService(new ConfigurationsSettings(context), new ActorProxyService(), context, actorType)).GetAwaiter().GetResult();

There is a way to do somethings like this:

builder.RegisterActor<StartupAgent>((context, actorType) => new StartupService(new ConfigurationsSettings(context), new ActorProxyService(), context, actorType)); ?

Thanks

How to use Serilog, Autofac and Service Fabric Actors together

I've been asked to come out of coding retirement to look at a production issue :-)

It seems we have a problem with disposing of Serilog objects judging by a memory dump.

In program.cs with register a module with this code

// In some places we don't have the container available so setting Log.Logger static
            
Log.Logger = ConfigureLogger().CreateLogger();

builder
     .Register(c => Log.Logger)
     .As<ILogger>()
     .SingleInstance();

We then register the Actor like this:

builder.RegisterActor<Ibis2Actor>()
                  .WithParameter(
                      (p, c) => p.ParameterType == typeof(ILogger),
                      (p, c) => c.Resolve<ILogger>().ForContext(new ActorEnricher(c.Resolve<ActorService>(),c.Resolve<ActorId>())));

The Actor Class looks like this:

public class Ibis2Actor : DeviceActor<Ibis2Reader>, IDeviceActor
    {
        public Ibis2Actor(
            ActorService actorService,
            ActorId actorId,
            DeviceContext deviceContext,
            ILogger logger) :
            base(actorService, actorId, deviceContext, logger)
        {
        }
...
}

Where DeviceActor is a abstract class inheriting from Microsoft.ServiceFabric.Actors.Runtime.Actor, maybe significantly neither the abstract class or the concrete class implement IDisposable.

My worry is that when the given ForContext returns an ILogger which does'nt implement IDisposable that this logger does not have cleanup up even after the Actor is deactivated.

Does anyone have a view about this approach or see what might be causing us to hold onto the Serilog objects ?

Should I make the Actor IDisposable or implement some kind of OnRelease in the Actor registration ?

Requiring Microsoft.ServiceFabric.Actors 2.4.164 raises warnings for later SF library versions

My Project description is:

  <ItemGroup>
    <PackageReference Include="Autofac" Version="4.6.1" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.0" />
    <PackageReference Include="Autofac.ServiceFabric" Version="1.0.0" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ServiceFabric" Version="6.0.*" />
    <PackageReference Include="Microsoft.ServiceFabric.Data" Version="2.8.*" />
    <PackageReference Include="Microsoft.ServiceFabric.Services" Version="2.8.*" />
    <PackageReference Include="Microsoft.ServiceFabric.Services.Remoting" Version="2.8.*" />
  </ItemGroup>

I get the following warnings on compilation

warning NU1608: Detected package version outside of dependency constraint: Microsoft.ServiceFabric.Actors 2.4.164 requires Microsoft.ServiceFabric (= 5.4.164) but version Microsoft.ServiceFabric 6.0.211 was resolved.
warning NU1608: Detected package version outside of dependency constraint: Microsoft.ServiceFabric.Actors 2.4.164 requires Microsoft.ServiceFabric.Data (= 2.4.164) but version Microsoft.ServiceFabric.Data 2.8.211 was resolved.
warning NU1608: Detected package version outside of dependency constraint: Microsoft.ServiceFabric.Actors 2.4.164 requires Microsoft.ServiceFabric.Services (= 2.4.164) but version Microsoft.ServiceFabric.Services 2.8.211 was resolved.

I would guess this is because I am not explicitly referencing a later version of Microsoft.ServiceFabric.Actors? Not really sure.

Not really sure if this is an issue, but I like not having warnings when I build!

P.S. Been using Autofac.ServiceFabric for nearly 6 months now and it's been working flawlessly! Thanks! ๐Ÿ˜„

Servicefabric context for logging

My logging library requires ServiceContext to be injected into it for logging Telemetry information.

var loggerFactory = new LoggerFactoryBuilder(context).CreateLoggerFactory(applicationInsightsKey); logger = loggerFactory.CreateLogger<MyStateless>();

Before implementing Autofac I was able to send the Context like this -

   ServiceRuntime.RegisterServiceAsync("MyStatelessType",
                    context =>
                    {
                        var applicationInsightsKey = FabricRuntime.GetActivationContext()
                            .GetConfigurationPackageObject("Config")
                            .Settings
                            .Sections["ConfigurationSection"]
                            .Parameters["ApplicationInsightsKey"]
                            .Value;

                        var loggerFactory = new LoggerFactoryBuilder(context).CreateLoggerFactory(applicationInsightsKey);
                        logger = loggerFactory.CreateLogger<MyStateless>();

                        return new MyStateless(context, logger);
                    }).GetAwaiter().GetResult();

However, I'm not sure how to get hold of Servicecontext now after implementing Autofac. Will be servicecontext be available only after builder.build()? In which case how can I register my logging library to Autofac. Please advise.

Thanks
Sai

Service class constructor never invoked

Hi,
My stateless service class constructor never invoked and there is no exception. Here is my stateless service class:

    public interface IRemindersService : IService
    {
    }
    public class RemindersService : StatelessService, IRemindersService
    {
        private readonly IBackgroundService _weeklyReminderService;
        private readonly IBackgroundService _remindersProcessor;
        private readonly IReminderRepository _remindersRepository;

        public RemindersService(
            StatelessServiceContext context, 
            IReminderRepository remindersRepository, 
            IBackgroundService weeklyReminderService, 
            IBackgroundService remindersProcessor)
            : base(context)
        {
            _remindersProcessor = remindersProcessor;
            _remindersRepository = remindersRepository;
            _weeklyReminderService = weeklyReminderService;
        }        
    }

and program.cs

    private static void Main()
    {
            try
            {               
                var builder = new ContainerBuilder();

                builder.RegisterType<AppSettings>().As<IAppSettings>();
                builder.RegisterType<ReminderQueries>().As<IReminderQueries>();
                builder.RegisterType<SqlReminderRepository>().As<IReminderRepository>();
                builder.RegisterType<MessageSender>().As<IMessageSender>();
                builder.RegisterType<WeeklyReminderService>().As<IBackgroundService>();
                builder.RegisterType<RemindersProcessor>().As<IBackgroundService>();
                //builder.RegisterType<RemindersService>().As<IRemindersService>();
               
                builder.RegisterServiceFabricSupport();
                
                builder.RegisterStatelessService<RemindersService>("RemindersServiceType");

                using (builder.Build())
                {
                    ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(RemindersService).Name);
                    Thread.Sleep(Timeout.Infinite);
                }
    }
    catch (Exception e)
    {
           ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
           throw;
     }

Singleton does not play nicely with ServiceContext dependency

Hi,

I just recently added a logger into my service fabric application to log all service fabric communication. Because of this, it is dependent on ServiceContext. When I register my type that is dependent (on something that is dependent on something) on ServiceContext as a SingleInstance, when the Service resolve's said type I get "The requested service 'System.Fabric.ServiceContext' has not been registered".

If i remove "SingleInstance()" from the registration, everything works business as usual. Now, making my service not a singleton, isn't the worst thing in the world, but i would love for it to function as a Singleton.

I've tried injecting it as a "Lazy", and a Func<Lazy>, and all result in the same error. Any ideas?

Autofac.ServiceFabric 2.2.0
ServiceFabric 3.4.641

Stack trace:
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable1 parameters)
at Fake.ApplicationInsights.Autofac.RegistrationExtension.<>c__DisplayClass1_01.<RegisterFakeApplicationInsights>b__1(IComponentContext c) in C:\Users\matth\Documents\Fake Code\FakeShared\Fake.ApplicationInsights\Source\Fake.ApplicationInsights\Autofac\RegistrationExtension.cs:line 59 at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass0_01.b__0(IComponentContext c, IEnumerable1 p) at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)

Thanks!

InstancePerMatchingLifetimeScope

This project should register the lifetime scope with a tag, so that additional things can be configured to register within the same scope but not lower. Since it promotes hosting multiple service instances in a single root container, this seems quite wise.

The tag should also be configurable.

Understanding scope in a stateless service.

I thought I'd ask here, as clearly you are interested in Service Fabric and an expert on all DI/IoC matters! ๐Ÿ˜„

How are service lifetimes managed within a service? What is the "scope" of an IService?

Let's say I have the following setup:

My Store/DAL:

public interface IUserStore
{
    Task<string> GetNameAsync(int Id);
}
public class UserStore : IUserStore
{
    private readonly IUserDbContext _context;

    public UserStore(IUserDbContext context) {
        _context = context;
    }

    public async Task<string> GetNameAsync(int id)
    {
        return _context.Users.FirstOrDefault(x => x.Id == id)?.Name;
    };
}

My Service interface:

public interface IUserService : IService
{
    Task<string> GetNameAsync(int Id);
}
public class UserService : IUserService
{
    private readonly IUserStore _userStore;

    public UserService(IUserStore userStore)
    {
        _userStore = userStore;    
    }

    public async Task<string> GetNameAsync(int id)
    {
        return await _userStore.GetName(id);
    }
}

I resolve my service using

ServiceProxy.Create<IUserService>(new Uri("fabric:/Users/UserService"))

I have been, perhaps naively, using Microsoft.Extensions.DependencyInjection. My service registration looked like this:

ActorRuntime.RegisterServiceAsync("UserService",
    context =>
    {
        var services = new ServiceCollection();
        services.AddDbContext<UserDbContext>(builder => builder.UseSqlServer("connectionString"));
        services.AddScoped<IUserDbContext, UserDbContext>();

        services.AddTransient<IUserStore, UserStore>();

        var serviceProvider = services .BuildServiceProvider();
        return serviceProvider.GetRequiredService<UserService>();
    }).GetAwaiter().GetResult();

This does not appear to work correctly. When I resolve my IUserService and call a method on it, it resolves to the already existing service which has already been constructed with its dependencies injected. With these stateless services there is no notion, or at least it appears that way, of a request/lifetime scope as you would have in say, an ASP.NET web application. The lifetime scope is basically the life of the service - which is indeterminate (read: infinite). This means I effectively have a singleton instance of the DbContext (and its corresponding change tracker) for the lifetime of my application. Which is pretty unacceptable really? Surely you'd want to resolve one per request to the service.

What I'd imagine you'd want is for it to work in a familiar manner -- i.e. similar to how service resolution works with ASP.NET web projects (see diagrams here).

I suppose what I am wondering is, how do (or how do you expect) constructor injection to work (with appropriate lifetimes) within a service?

One solution is to use Actors, since each call to create a *Actor from the *ActorService creates a new instance of *Actor. However I am not entirely sure if this is an entirely sensible solution.


This of course isn't directly related to Autofac.ServiceFabric but with DI and Service Fabric Services in general, which you may be able to address! I did refactor the above to use this library, but the same issue remains, my dependencies are't (can't?) be recreated per request to my IService. The only (I don't mean that in a diminutive way at all!!) thing I believe this library does additionally is that when tearing down a service it GC's stuff correctly.

Service not running after transistioning from alpha-1 to alpha-2

Briefly tried to migrate a project from alpha-1 to alpha-2 today and after fixing up the code the SF app would deploy but none of the Services would start.

They didn't appear to error, they just didn't get activated. I suspect it's my understanding of how the refactored package should work.

A sample of the usage would be great.

MissingMethodException after update to Autofac 5.0.0

Description

Updating Autofac to 5.0.0 (released last day) causes a MissingMethodException with the message:

Method not found: 'Autofac.ContainerBuilder Autofac.ContainerBuilder.RegisterBuildCallback(System.Action`1<Autofac.IContainer>)'.

The Autofac release notes advertises some changes in the build callbacks.

App type

<TargetFramework>netcoreapp3.0</TargetFramework>
<OutputType>Exe</OutputType>

Relevant assemblies version:

<PackageReference Include="Autofac" Version="5.0.0" />
<PackageReference Include="Autofac.ServiceFabric" Version="2.2.0" />
<PackageReference Include="Microsoft.Diagnostics.EventFlow.ServiceFabric" Version="1.5.1" />
<PackageReference Include="Microsoft.ServiceFabric.Diagnostics.Internal" Version="4.0.457" />
<PackageReference Include="Microsoft.ServiceFabric.Services.Remoting" Version="4.0.457" />

Stack trace:

   at Autofac.Integration.ServiceFabric.AutofacServiceExtensions.RegisterStatefulService[TService](ContainerBuilder builder, String serviceTypeName, Object lifetimeScopeTag)
   at MyApp.Host.IoC.ServiceFabricModule.Load(ContainerBuilder builder) in D:\Sources\MyApp\src\MyApp.Host\IoC\ServiceFabricModule.cs:line 23
   at Autofac.Module.Configure(IComponentRegistryBuilder componentRegistry)
   at Autofac.ContainerBuilder.Build(IComponentRegistryBuilder componentRegistry, Boolean excludeDefaultModules)
   at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
   at MyApp.Host.Bootstrapper.ConfigureModules() in D:\Sources\MyApp\src\MyApp.Host\Bootstrapper.cs:line 23
   at MyApp.Host.Program.<Main>d__0.MoveNext() in D:\Sources\MyApp\src\MyApp.Host\Program.cs:line 18

Cannot resolve parameter 'System.Fabric.StatefulServiceContext serviceContext'

Hi, I am trying to register the ReliableStateManager in the container. The constructor requires StatefulServiceContext and a ReliableStateManagerConfiguration object. No matter how I try registering it I end up with the following exception:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Microsoft.ServiceFabric.Data.ReliableStateManager' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.Fabric.StatefulServiceContext serviceContext' of constructor 'Void .ctor(System.Fabric.StatefulServiceContext, Microsoft.ServiceFabric.Data.ReliableStateManagerConfiguration)'.

I have tried registering the state manager like this:

builder.Register(c => new ReliableStateManager(c.Resolve<StatefulServiceContext>(), null)).As<IReliableStateManager>().SingleInstance();

and

builder.RegisterType<ReliableStateManager>().As<IReliableStateManager>().WithParameter("configuration", null).SingleInstance();

before calling

builder.RegisterStatefulService<TService>(serviceType);

Before using the Autofac.ServiceFabric 2.2.0 package, we wired everything up manually, meaning registering the context and state manager in the container and it was working as expected.

I see that the StatefulServiceContext is registered just before the service is resolved. It this a timing issue maybe?

Service proxy and logging

Hi

I'm looking for a way to log all calls to Actors/Services methods through the service proxy. I want log all methods on client and server sides. Client side is easy to implement but I don't know how to do it on remote side with existed features.

It would be nice to return here IRegistrationBuilder and pass it to builder.RegisterActor method. So I can add some interceptor.

internal static void RegisterServiceWithInterception<TService, TInterceptor>(this ContainerBuilder builder)

The same for stateless and stateful services

What do you think?

Autowired Properties

In another project where we use Autofac we massively used the "WithAutoWiredProperties" concept, we also customize the properties resolutor in order to drive the choice of the properties to AutoWire using a custom Attribute.
Everything worked fine and we were happy.
As far as I've understood, it is not possible to do the same with this Extension, I mean, it is not possible to add some "With" to the ServiceFabric services/actors registration.
What can be the solution to add such a behavior?

Accessing CodePackageActivationContext

For example, pulling configuration data from the CodePackage needed for service initialization

ServiceRuntime.RegisterServiceAsync("UserService",
    context =>
    {
        var configurationPackage = context.CodePackageActivationContext.GetConfigurationPackageObject("Config");
        var userStoreConnectionString = configurationPackage.Settings.Sections["UserStore"].Parameters["ConnectionString"].Value;


        var services = new ServiceCollection();
        services.AddDbContext<UserDbContext>(builder => builder.UseSqlServer(userStoreConnectionString ));
        services.AddScoped<IUserDbContext, UserDbContext>();
        services.AddScoped<IUserStore, UserStore>();

        var serviceProvider = services.BuildServiceProvider();
        return serviceProvider.GetRequiredService<UserService>();
    }).GetAwaiter().GetResult();

Is there a way to achieve this currently? Or do I have to think of a different way of storing configuration values? -- Is there a recommended method for retrieving service configuration data?

Lifetime scope for Actor instance

I'm struggling with service resolution for my Actors. I have a command handler pattern that resolves ICommandHandler generic handlers, and I have a repository service that the command handlers use. When I route the command to all the handlers, they use that repository service to store the results in a queue. I configured the repository service as a SingleInstance such that the higher-level Actor method and the generic command handlers would all be using the same instance.

I found out during integration that the SingleInstance lifetime for an Actor service is the entire service - i.e., each Actor instance created during the runtime is using the same repository with a queue intended to serve only one Actor instance. Because of the pattern of generic command handler resolution, I don't think the faux-per-request lifetime scope approach will work for me, but I am really hoping I'm wrong about that.

How would I go about having a shared singleton-like dependency registered within the scope of an Actor instance?

I can provide some sample code if that helps.

Instanceperrequest equivalent Scope in Statefulservice

I have an exising web app that I'm migrating into SeviceFabric and got struck at this a strange problem. Is there an equivalent scope of Instanceperrequest in stateful service ? I have few objects that only needs to be instantiated once per request via ServiceRemoting to my stateful service. However, I cant find it anything that I could use in Servicefabric, please advise.

ServiceFabricModule is internal, visible to Autofac RegisterAssemblyModules, but cannot be constructed

The Autofac Module in the project is set up in such a way that it's hit by the Autofac RegisterAssemblyModules method, which tries to construct it. However, since it has no default constructor, this fails.

What this means is the mere existence of the module within a project that is doing dynamic assembly loading (and loading AF modules) breaks it.

It looks like the intention is to call it from RegisterServiceFabricSupport. That's fine. But it would be nice if the module could either be unreachable by Autofac in some way.

This is new in 2.1.0.

2.0.0 did not have this issue.

RegisterStatelessService doesn't work inside Modules

RegisterStatelessService() called within a Module.Load() results in the StatelessService instance not being spun up/created. There are no errors, just nothing happens. Interestingly, RegisterServiceFabricSupport() can be placed in the module and everything works as expected, as long as RegisterStatelessService() is outside of a Module.Load().

Reduced extensibility due to access restrictions in classes and methods

For our Service Fabric application, I have found that there is some missing functionality in the Autofac.ServiceFabric.

To implement state backup and restore from stateful actors, in Service Fabric it is needed to create a "custom" ActorService that overrides some of the base methods from the StatefulServiceBase superclass, however, in the Autofac.ServiceFabric extensions, the creation of the actors to ActorService (in the class ActorFactoryRegistration), are hardcoded and it can only be done by creating a fork and make changes in the project.

To allow the creation of a CustomActorService, it should be needed to open the libraries a little bit more and some of the elements marked as "internal" be made "public". This way, it would be possible to implement a custom implementation of IActorFactoryRegistration and then register our implementation to be able to create our custom ActorServices instances.

Other option it would be to find a way to configure the type to be used for the ActorService instead of having it hardcoded.

In any case, opening the library a bit more by making it more "public" and less "internal" could help reduce the need of creating forks of the repository to customize the classes to achieve some behaviour that is not supported yet.

Allow logging exceptions during service instantiation

I don't know if there is already a way of doing this, but I need to log the exceptions during service instantiation. Normally these exceptions are Autofac exceptions that cannot resolve a service dependency, but they could also be exceptions during the constructor execution.

Maybe we could pass an Action to RegisterServiceFabricSupport or to the service registration methods? like

builder.RegisterServiceFabricSupport(e=> logger.Error(e, "Exception instantiating service");

or

builder.RegisterStatelessService<MyServiceType>(myServiceTypeName, e=> logger.Error(e, "Exception instantiating MyServiceType");

How to communicate to stateful service use remoting?

I have a stateless service (web api) that talks to stateful service over remoting. On the stateful service I register with autofac, and same goes for the stateless. However one of the ways to communicate to the stateful service is remoting, is there some way using autofac to locate services instead of me having to write the following code?

IMyService helloWorldClient = ServiceProxy.Create(new Uri("fabric:/MyApplication/MyHelloWorldService"));

string message = await helloWorldClient.HelloWorldAsync();

Dynamic Proxy breaks optional constructor arguments

I've got a service with a ctor arg with a default value of null. Autofac throws saying it can't find a service for this parameter. Which is correct, there isn't one. But it's optional.

I suspect it's the dynamic proxy. Probably not duplicating the default.

Access denied in RegisterActor

I've created a simple app, just the template generated by Visual Studio for .net core, to test this package integration. But I'm experimenting a problem with the following code:

private static void Main()
        {
            try
            {
                var builder = new ContainerBuilder();

                builder.RegisterServiceFabricSupport();
                builder.RegisterActor<TestingActorSystem>();

                using (builder.Build())
                {
                    Thread.Sleep(Timeout.Infinite);
                }
            }
            catch (Exception e)
            {
                ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
                throw;
            }
        }

The line builder.RegisterActor(); is throwing:

System.TypeLoadException: Access is denied: 'TestingActorSystem.TestingActorSystem'.
   at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type)
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
   at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
   at Autofac.Extras.DynamicProxy.RegistrationExtensions.EnableClassInterceptors[TLimit,TConcreteReflectionActivatorData,TRegistrationStyle](IRegistrationBuilder`3 registration, ProxyGenerationOptions options, Type[] additionalInterfaces)
   at Autofac.Integration.ServiceFabric.RegistrationExtensions.RegisterServiceWithInterception[TService,TInterceptor](ContainerBuilder builder)
   at Autofac.Integration.ServiceFabric.AutofacActorExtensions.RegisterActor[TActor](ContainerBuilder builder, Func`3 stateManagerFactory, IActorStateProvider stateProvider, ActorServiceSettings settings)
   at TestingActorSystem.Program.Main() in c:\dev\TestActorSystem\TestingActorSystem\Program.cs:line 24}	System.Exception {System.TypeLoadException

Any help?

Autofac.ServiceFabric Dependencies Incompatible With Microsoft.ServiceFabric.AspNetCore.Kestrel

Any chance to update the reference packages? I'm getting this error when trying to use ASP.NET Core Kestrel:

Error CS1705 Assembly 'Microsoft.ServiceFabric.AspNetCore.Kestrel' with identity 'Microsoft.ServiceFabric.AspNetCore.Kestrel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' uses 'System.Fabric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' which has a higher version than referenced assembly 'System.Fabric' with identity 'System.Fabric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

This is because Autofac.ServiceFabric depends on Microsoft.ServiceFabric.Actors which in turn depends on Microsoft.ServiceFabric, which again depends on System.Fabric (the incompatible version).

Also would it be better to break out the Actors vs Stateless vs Stateful integrations into their own packages?

Create a 1.0 release

There have been a few good PRs and a number of pre-release packages so I think it's time to push out the official release.

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.