Я пытаюсь добавить IoC в свой api и продолжаю получать эту ошибку:
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>();
}
}
}
Я попытался поставить это (но не уверен, куда он должен идти):
[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
а также попытался пометить класс Program как общедоступный, но, похоже, это не сработало
Обновлено:
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));
}
}
}
Я не уверен, что еще может помочь, что-то конкретное, что вам нужно увидеть?
Inovatic.SF.Windows.Facade.Facade
это первая странность сообщения об ошибке, у меня Inovatic.SF.Windows.Facade но не Inovatic.SF.Windows.Facade.Facade
Итак, позвольте мне сказать прямо: у вас нет класса Facade
в пространстве имен namespace Inovatic.SF.Windows.Facade
? Можете ли вы опубликовать полный код (включая пространства имен) Facade
, который у вас есть делать?
Простите, недоразумение, основной пост отредактирован
Вы должны сделать класс Facade
общедоступным и удалить ключевое слово sealed
(поскольку autofac создает прокси-класс, который наследуется от вашего класса. Если он запечатан, это запрещено).
Так что измени
internal sealed class Facade : StatelessService
к
public class Facade : StatelessService
Тогда тебе это больше не нужно
[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
это не повлечет за собой никаких проблем с безопасностью?
Почему? делая тип общедоступным, только другие сборки, которые зависят от этой сборки, могут использовать этот класс. Но это под вашим контролем. О каких проблемах безопасности мы говорим? Это не волшебным образом сделает эту услугу общедоступной из Интернета, если вы так думаете.
Извините за задержку, переключение на публичный закрытый класс Facade или публичный класс Facade делает службу, по-видимому, нездоровой ...
Да ладно, работает, а вот "пломбу" все равно нужно удалить
да, это потому, что autofac создает прокси-класс, который наследуется от вашего класса. Если он запломбирован, это запрещено. Я обновлю свой ответ соответственно
Вам необходимо разместить код своей услуги. Не из
program.cs