Search code examples
azureasp.net-core-2.0autofacazure-service-fabric

service fabric asp .net core IoC error : cannot be dynamically proxied


I'm trying to put some IoC in my api and keep getting this error :

The type Inovatic.SF.Windows.Facade.Facade cannot be dynamically proxied. Service types must not be sealed and need to be visible to the DynamicProxyGenAssembly2 assembly. This can be achieved by making the type public or adding the InternalsVisibleToAttribute to the assembly containing the type. e.g. [assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]

program.cs:
//[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
namespace Inovatic.SF.Windows.Facade
{
internal static class Program
{
    /// <summary>
    /// This is the entry point of the service host process.
    /// </summary>
    private static void Main()
    {
        try
        {
            var builder = new ContainerBuilder();
            builder.RegisterModule(new GlobalAutofacModule());
            builder.RegisterServiceFabricSupport();
            builder.RegisterStatelessService<Facade>("Inovatic.SF.Windows.FacadeType");

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

public class GlobalAutofacModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<ConfigSettings>();
        builder.RegisterType<PaymentRepository>().As<IPaymentRepository>();
    }
}

}

I've tried to put this (but not sure where it should go) :

[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]

and also tried to mark the Program class as public but that doesn't seem to work

EDIT:

namespace Inovatic.SF.Windows.Facade
{
internal sealed class Facade : StatelessService
{
    public Facade(StatelessServiceContext context)
        : base(context)
    { 
        var telemetryConfig = TelemetryConfiguration.Active;
        telemetryConfig.InstrumentationKey = Environment.GetEnvironmentVariable("ApplicationInsightsKey");
        FabricTelemetryInitializerExtension.SetServiceCallContext(context);
    }

    /// <summary>
    /// Optional override to create listeners (like tcp, http) for this service instance.
    /// </summary>
    /// <returns>The collection of listeners.</returns>
    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        var endpoints = Context.CodePackageActivationContext.GetEndpoints()
            .Where(endpoint => endpoint.Protocol == EndpointProtocol.Http 
            || endpoint.Protocol == EndpointProtocol.Https);

        return endpoints.Select(endpoint => new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, endpoint.Name, (url, listener) =>
            {
                ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                return new WebHostBuilder()
                    .UseKestrel(options =>
                    {
                        if (endpoint.Protocol == EndpointProtocol.Http)
                            options.Listen(IPAddress.Any, endpoint.Port);
                        else if (endpoint.Protocol == EndpointProtocol.Https)
                            options.Listen(IPAddress.Any, endpoint.Port,
                                listenOptions => listenOptions.UseHttps(Certificates.GetCertificateFromLocalStore(
                                        Environment.GetEnvironmentVariable("ClusterCertifThumbprint"))));
                    })
                    .ConfigureServices(
                        services =>
                        {
                            services
                                .AddSingleton(new ConfigSettings())
                                .AddSingleton(serviceContext)
                                .AddSingleton(new HttpClient())
                                .AddSingleton(new FabricClient());
                        })
                    .UseContentRoot(Directory.GetCurrentDirectory())
                    .UseStartup<Startup>()
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"))
                    .UseUrls(url)
                    .UseApplicationInsights()
                    .Build();
            }), endpoint.Name));
    }
}

}


Solution

  • You have to make the Facade class public and remove the sealed keyword (Because the autofac creates a proxy class that inherits from your class. If it is sealed that is prohibited).

    So change

    internal sealed class Facade : StatelessService
    

    to

    public class Facade : StatelessService
    

    Then you do not need this anymore

    [assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]