can't using reference a service in project net core 3.1 - c#

I have a project using net core 3.1, I add reference service success but i not using it.
it alert error: Service_MDMSSoapClient does not contain a contrustor that take 0 arguments when I want using it.
my code
public class Program
{
public static void Main(string[] args)
{
**Service_MDMSSoapClient a = new Service_MDMSSoapClient();**
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
please help me
how to resolt problem

The object simply can't be created with no arguments (there are three other possibilities regarding to the info text provided -> +3 overloads).
You can hover "Service_MDMSSoapClient() and press Ctrl + left click to be redirected into the class definition to sift what arguments are possible to create that new object.
Is that what you already did? There is the partial flag next to the class name, so possible that there is another constructor in another partial class file available.

Related

How to use dependency injection for transient instances in async tasks loop

There is a class that implements an interface called SomethingManager.cs
like:
public class SomethingManager : ISomethingManager
This is a worker service in .net 6 and there is another class library project in the same solution that contains the interface and implementation of SomethingManager.
Dependencies are being registered in the worker service project like
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureServices((hostContext, services) =>
{
//AddSingleton or Transient here?
services.AddSingleton<ISomethingManager, SomethingManager>();
...
The problem is that, in the entrypoint project that works in an async way,there is a loop like:
foreach (xml in xmls)
{
tasks.Add(StartProcessAsync(xml));
}
await Task.WhenAll(tasks);
Inside StartProcessAsync it uses SomethingManager instance hat was previously registered and injected in the constructor.
The problem is that the class SomethingManager has some private members that are supposed to be unique for every task and I noticed that in this way it causes fatal errors between the tasks.Actualy this class needs to share a sessionId that a method .Connect() is giving the value every time.We have to call .Connect() method, one time before other actions,inside every task.
So,
My question is how can I register the SomethingManager with Dependency Injection and every task that uses this instance (which is registered with DI) to have different values for its private members?
And, if can't do it in this way, am I supposed to create new instance for this every time?
public Task StartProcessAsync(xmlFileInfo xml)
{
return Task.Run(async () =>
{
//this one doesn't work inside tasks loop it cases problems because
//the sessionId that contains has to be different for every task
//_somethingManager.DoSomething();
//Like this?
var somethingManager= SomethingManager(_someSettings);
somethingManager.DoSomething();
var mem = somethingManager.ThePrivateMember;
//another object which has also private members in the same class.
});
}

ServicesProvider / Dependency Injection in C# Unit test classes

I have serveal Unit Tests projects UT_A, UT_B, UT_C which all include a common UT_Common project containing common stuff for A, B, C.
I want A, B, C to have their own ServiceProvider to handle their DI, their own IConfiguration (Appsettings) etc...
I have coded in A, B, C project a class that builds their own dedicated
public static class ServicesBuilder_A
{
public static IHost ServicesHost { get; }
static ServicesBuilder()
{
IConfigurationRoot configurationRoot = null;
IHostBuilder host = Host.CreateDefaultBuilder().......
.....
ServicesHost = host.Build();
}
}
So the IHost is singleton, initialized at first use.
Now, when I start my unit tests of UT_A project, at some point I will need project UT_Common to access to the AppSettings UT_A appsettings and do stuff based on this specific file.
And of course, when I start UT_B, I need UT_Common to use UT_B IHost.
Since TU_COmmon is included in TU_A, UT_B, it does not know the static classes used in UT_A and UT_B and can't use them directly.
I firstly thought of setting a static class in UT_Common that would expose an IHost that I would set in UT_A, UT_B, when setting their IHost.
Adding at the end of previous building method:
public static class ServicesBuilderContainer
{
public static IHost ServicesHost { get; set; }
}
Into the IHost conf of UT_A, UT_B:
ServicesBuilderContainer.ServicesHost = ServicesHost;
But it does not really work, as UT_A.ServicesBuilder_A static ctor will only run when I try to get its IHost.
If I need to access UT_Common.ServicesBuilderContainer.ServicesHost first, then UT_A.ServicesBuilder_A.ServicesHost will not have been initialized yet so UT_Common.ServicesBuilderContainer.ServicesHost will be empty.
I am sure I am doing things wrong but I do not know how to fix this mess in a good way.
Thx for your advices :)
EDIT:
Well I am used to using DI in .NETCore controllers / Service classes :
public class MyController : ControllerBase
{
public MyController(IMyInterface myInterface)
{
...
}
}
But I did not find a way to have something similar in my own classes.
I suppose that in the case of Controllers, there is some .NetCore magic behind the scene that does not apply to my own classes?

object lifetime using factory method for dependency injection in .net 5

I'm playing with .net 5 dependency injection, which is very useful. From various sources, like the accepted answer of this question Dependency injection, inject with parameters , I learn that using a factory method in AddTransient/Scoped/Singleton, the container will not dispose the object created, even if the object implements IDisposable. But the following code tells me clearly that the objects are disposed automatically (which is great, but I'd like to understand the story behind).
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ConsoleDI.Example
{
public class TransientDisposable : IDisposable
{
public void Dispose() => Console.WriteLine($"{nameof(TransientDisposable)}.Dispose()");
}
public class ScopedDisposable : IDisposable
{
public void Dispose() => Console.WriteLine($"{nameof(ScopedDisposable)}.Dispose()");
}
public class SingletonDisposable : IDisposable
{
public void Dispose() => Console.WriteLine($"{nameof(SingletonDisposable)}.Dispose()");
}
class Program
{
static void Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
ExemplifyDisposableScoping(host.Services, "Scope 1");
Console.WriteLine();
ExemplifyDisposableScoping(host.Services, "Scope 2");
Console.WriteLine();
host.Run();
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddTransient<TransientDisposable>(_ => new TransientDisposable())
.AddScoped<ScopedDisposable>(_ => new ScopedDisposable())
.AddSingleton<SingletonDisposable>(_ => new SingletonDisposable())
);
static void ExemplifyDisposableScoping(IServiceProvider services, string scope)
{
Console.WriteLine($"{scope}...");
using IServiceScope serviceScope = services.CreateScope();
IServiceProvider provider = serviceScope.ServiceProvider;
_ = provider.GetRequiredService<TransientDisposable>();
_ = provider.GetRequiredService<ScopedDisposable>();
_ = provider.GetRequiredService<SingletonDisposable>();
}
}
}
output:
Scope 1...
ScopedDisposable.Dispose()
TransientDisposable.Dispose()
Scope 2...
ScopedDisposable.Dispose()
TransientDisposable.Dispose()
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/zhjun/Work/tmp/ConsoleDI.Example
^Cinfo: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
SingletonDisposable.Dispose()
So why is this? Is this a .net 5 DI container improvement? or is this always this way?
I wouldn't say that the selected answer is incorrect, but at the very least it is incomplete, because the only registration that does not cause instances to be disposed is the AddSingleton<T>(T) call. Everything else (including instances returned from registered factory delegates for transient, scoped, and singleton) will be disposed of. This behavior is 'by design', specified in MS.DI's unit tests, and has been this way since version 1.0. The official Microsoft documentation is quite clear about this:
In the following example, the services are created by the service container and disposed automatically:
services.AddScoped<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<IService3>(sp => new Service3());
In the following example: [...] The framework doesn't dispose of the services automatically.
services.AddSingleton<Service1>(new Service1());
services.AddSingleton(new Service2());
The central idea behind this is that with AddSingleton<T>(T) you provide an already created instance or, in the terminology of Autofac, 'externally owned'. The supplied instance already lives before the container exists and it might be the user's goal to keep using that object long after the container was disposed of, which is why such instance is not disposed of at that point.

use hangfire as windows service by topshelf (.net core 2.2)

I am trying to use hangfire as windows service by using Topshelf in console app .net core 2.2 . I just want to load hangfire dashboard, not adding any job or anything else.
Program.cs
using System;
using Topshelf;
namespace HangfireAsService
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(config =>
{
config.Service<Bootstrap>(service =>
{
service.ConstructUsing(s => new Bootstrap());
service.WhenStarted(s => s.Start());
service.WhenStopped(s => s.Stop());
});
config.RunAsLocalSystem();
config.SetDescription("Hangfire as windows Service for DataCrawling Project");
config.SetDisplayName("Hangfire Service Custom");
});
}
}
}
Bootstrap.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Owin.Hosting;
namespace HangfireAsService
{
public class Bootstrap
{
private IDisposable _host;
public void Start()
{
var options = new StartOptions { Port = 8999 };
_host = WebApp.Start<Startup>(options);
Console.WriteLine();
Console.WriteLine("Hangfire has started");
Console.WriteLine("Dashboard is available at http://localhost:8999/hangfire");
Console.WriteLine();
}
public void Stop()
{
_host.Dispose();
}
}
}
Startup.cs
using Hangfire;
using Microsoft.AspNetCore.Builder;
using Owin;
using System;
using System.Collections.Generic;
using System.Text;
namespace HangfireAsService
{
public class Startup
{
public void Configuration(IApplicationBuilder appBuilder)
{
GlobalConfiguration.Configuration
.UseSqlServerStorage("Server=111.111.11.1\\INS2017; Database=Hangfire; user=sa;
password=;");
appBuilder.UseHangfireDashboard();
appBuilder.UseHangfireServer();
}
}
}
As you can see, I created 2 classes for my self-host owin and after reviewing the event viewer I got the error displayed below:
The description for Event ID 0 from source HangfireAsService cannot be
found. Either the component that raises this event is not installed on
your local computer or the installation is corrupted. You can install
or repair the component on the local computer.
If the event originated on another computer, the display information
had to be saved with the event.
The following information was included with the event:
Service cannot be started. System.NullReferenceException: Object
reference not set to an instance of an object. at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.FromConfigImplementation..ctor()
at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.<>c.b__1_0()
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T&
target, Func1 valueFactory) at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.LoadFromConfig(IDictionary2
settings) at
Microsoft.Owin.Hosting.Engine.StartContext..ctor(StartOptions options)
at
Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions
options) at
Microsoft.Owin.Hosting.Starter.HostingStarter.Start(StartOptions
options) at HangfireAsService.Bootstrap.Start() in
C:\MyWorkSpace\Data
Crawling\dataCrawlingConsole\HangfireAsService\Bootstrap.cs:line 17
at HangfireAsService.Program.<>c.b__0_3(Bootstrap s) in
C:\MyWorkSpace\Data
Crawling\dataCrawlingConsole\HangfireAsService\Program.cs:line 15
at
Topshelf.ServiceConfiguratorExtensions.<>c__DisplayClass2_01.<WhenStarted>b__0(T
service, HostControl control) at
Topshelf.Builders.DelegateServiceBuilder1.DelegateServiceHandle.Start(HostControl
hostControl) at
Topshelf.Runtime.Windows.WindowsServiceHost.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object
state)
The message resource is present, but the message was not found in the message table.
i used same code inside .net framework instead of .net core and work perfectly.after a test something else i notice this problem because of OWIN happened so after i removed it and use using .net core self-host instead of OWIN everything work perfectly.
below link will help you a lot.
https://medium.com/#tocalai/create-windows-service-using-net-core-console-application-dc2f278bbe42

How to pass a config file as parameter to a console application .Net

I need a sample/example demonstrating how to pass a config file as a parameter to a console application in .Net
Pass it in command line parameters, in args[].
Something like this.
class Program
{
static void Main(string[] args)
{
if (args == null)
{
Console.WriteLine("args is null."); // Check for null array
}
else
{
// use args to get passed config file path
}
}
}
~~~ How to call the program ~~~
C:\ConsoleApplication1.exe "your config
file path" (like C:\config\app.config)
Do you have access to target console application source code? Is it .NET application?
If yes do next: add target app as a reference to the source application project (exe can be added like dll, there is no difference). And call some public method.
// target.exe code
namespace Target {
public class MyConfig { }
public class Program {
static void Main(string[] args) { }
public static void EntryPoint(MyConfig conf) { }
}
}
// source.exe code
namespace Source {
class Program {
static void Main(string[] args) {
Target.MyConfig conf = new Target.Config();
Target.Program.EntryPoint(conf);
}
}
}
If u want to store data like FileOutputDirectory you can also use Settings page instead of config file. Settings page is easy to configure and use. Read more at msdn website: link text

Categories