Unity resolution for a customTraceListener? - c#

I have a custom trace listener, with a simple constructor;
public MyTraceListener(ISomething something)
{
_something = something;
}
This is wired to my web app through system.diagnostics in the web.config.. However, it never seems to fire this. How do I get unity to resolve this? Do I need to edit my web.config somehow? If I add a default constructor that fires, so would the correct approach be to have the default constructor do some sort of resolve on itself?

Unfortunately, you're kind of stuck. The tracing system doesn't give you the opportunity to take over object creation, so Unity doesn't get a chance to do constructor injection. The system will new up the trace listener.
The best you can do is to set your dependencies as properties, rather than constructor dependencies, and then grab the trace listener object after it's been created and call container.BuildUp on it to get properties injected.

Did you register ISomething with Unity either in your code or in your web.config?
Something like
var container = new UnityContainer().RegisterType<ISomething, Something>();
or via config file as described [here]
Do you call Unity to resolve your custom TraceListener?
var myTraceListener = container.Resolve<MyTraceListener>();
or do you inject your listener in some other class where it should be used so that Unity resolves the listener as a parameter?

Related

MAUI dependency injection service resolve in Program.cs

MAUI has dependency injection setup similar to what ASP.NET Core has in the Startup.cs class. This one is set in MauiProgram.cs file by default.
My question is: How can I get a service instance in this file after services registration? I guess, one solution will be the following, but then I must edit this code also if the constrctors of these services change during time:
var keyValueStore = new PreferencesKeyValueStore();
var accountService = new AccountService(keyValueStore);
var profileService = new ProfileService(keyValueStore);
builder.Services.AddSingleton<IKeyValueStore>(keyValueStore);
builder.Services.AddSingleton<IAccountService>(accountService);
builder.Services.AddSingleton<IProfileService>(profileService);
//Here now I can use accountService and profileService to do something
I can not find more elegant solution that will return the service instance for me from the DI container. Something like:
builder.Services.AddSingleton<IKeyValueStore, PreferencesKeyValueStore>();
builder.Services.AddSingleton<IAccountService, AccountService>;
builder.Services.AddSingleton<IProfileService, ProfileService>();
//Now I can't perform something like: var accountService = diContainer.GetInstance<IAccountService>(); or similar.
I don't know how to reach di container and ask it to provide me registered instance.
Actually, the documentation provided a simple way to do so.
Check it here
They recommended to use the Handler property of any object of type Element, there you can write the code :
// Considering you want to resolve a service from your custom interface IMyService
var service = this.Handler.MauiContext.Services.GetService<IMyService>();
// Then you can use the resolved service..
But there are some issues, personally it never worked for me, the Handler property may be null because of the lifecycle of the Element you are calling it on.
To avoid this issue, use a full line like:
var service = Application.Current.MainPage
.Handler
.MauiContext
.Services
.GetService<IMyService>();
// Then you can use the resolved service..
This works fine for me
Hope it helps you ..

Resolve type with explicit instance

I use AutoFac. I have to resolve a type with an explicit instance which I get from another service.
For example: I have an instance of type Client which I get from somewhere (not from the container).
I want to configure the Autofac container so that always when an object of type Client should be resolved, it should return my instance.
Problem is that I don't have this instance at the time, when I configure the container with the Containerbuilder - so I cannot use for example LambdaRegistration.
Is there another solution for solving my problem?
You can do the following:
MyService service = null;
builder.Register(c => service).As<IMyService>();
// Later on
service = new MyService();
Depending on your needs there are quite some variations of this approach possible, such as:
Send a 'setter' delegate to some initialization code that will call the delegate after the service gets created, e.g. MyServiceInitializer.AfterInitialization(s => service = s);
Promote the service variable to a class property and provide that new wrapper to the initialization
Hide access to the service behind specific read and write abstractions, e.g. interface IMyServiceContext { IMyService Current { get; } } and interface IMyServiceSetter { void SetCurrent(IMyService service); }.
Prevent Autofac from accidentally resolving the service before it is initialized by throwing an exception instead of throwing null, e.g. Register(c => service ?? throw new InvalidOperationException("..."))
It's important to note, however, that in general, the creation of components should be fast and reliable. The fact that your component isn't available at startup is likely because it requires I/O to setup. This is a situation should should try to prevent, for instance by hiding it behind an abstraction completely. This allows you to implement a Proxy that allows the real service to be lazy loaded.
Hopefully this gives you some clues on how to solve this.

How to register dependent services

I register the HttpClient like:
services.AddSingleton<HttpClient>();
then further down in the code I want to register another interface that depends on this:
services.AddSingleton<IMyRepository>(
new MyRepository("<string>",
"<string>",
"<string>",
???,
logger));
So I am not sure what to put in ???. I could put 'new HttpClient()' but that kind of defeats the purpose of registering HttpClient. I basically need the method that I call to get the reference that has already been added. Ideas?
Thank you.
Resolve it from the service provider:
services.AddSingleton<IMyRepository>(serviceProvider =>
new MyRepository("<string>",
"<string>",
"<string>",
serviceProvider.GetRequiredService<HttpClient>(),
logger));
By the way, you probably want to use HttpClientFactory (services.AddHttpClient();) instead of services.AddSingleton<HttpClient>();.
See You're (probably still) using HttpClient wrong and it is destabilizing your software for information on the DNS issues that occur with a long-lived static (or singleton) HttpClient and why you should use HttpClientFactory.

ASP.NET Core access service in Startup.cs ConfigureServices method

I need to access a service inside ConfigureServices method in Startup.cs and I do this:
services.AddScoped<ICustomService, CustomService>();
var sp = services.BuildServiceProvider();
var service = sp.GetService<ICustomService>(); // this is null
However var service above is always null.
What do i do wrong?
I had this sort of problem - I had a singleton 'settings' service which I wanted to use. I solved it by Actually creating one then registering that exact instance with DI via the overload that lets you specify a 'provider', rather than just registering the class, and adding a nice big comment explaining this:
var settingsService = new SettingsService(_hostingEnvironment);
//Add a concrete settings service which is then registered as the de facto settings service for all time.
//we need to do this as we want to use the settings in this method, and there isn't a satisfactory method to
//pull it back out of the IServiceCollection here (we could build a provider, but then that's not the same provider
//as would be build later... at least this way I have the exact class I'll be using.
services.AddSingleton<ISettingsService, SettingsService>((p) => settingsService);
..
..
..
var thing = settingsService.SomeSettingIWant();
If what you want isn't a singleton but is something transient, then I guess you can just create a concrete class for it right there? I know it probably feels a bit like cheating, but it would work fine...

Missing Dependency Injection Register? Cannot resolve parameter X

I am a little lost as to where I need to look to resolve the error message below.
The history is that I added a new service object to the project and instantiate / inject it when a new section of the site is accessed. (MVC 3 site repository/service architecture).
The error is:
Cannot resolve parameter 'XService pl_xService' of constructor 'Void .ctor(.....
Now this is straight forward enough to understand. The newly added parameter XService can't be resolved...
The error is thrown by Autofac.core.dependency but I am not sure where / how I would register my new object for Autofac.
I understand you have no clue how my project is setup so I'm just looking for greater understanding of what is going on thus enabling me to track down where I need to register my new service object with Autofac etc.
FWIW:
Controller for new section of the site:
public partial class NewSectionController : BaseController
{
private readonly IPL_XService _pl_xService;
#region Constructors
public NewSectionController(IPL_XService pl_xService,....)
{
this._pl_forumService = pl_forumService;
}
.....controller actions, helpers, utilities etc.........
}
Since I am in waters I have not spent much time (if any really) in please let me know of any other code, style, architecture etc. that I can post to help make the question better.
Thank You
Just search for ContainerBuilder class, and then add this code:
var builder = new ContainerBuilder();
builder.RegisterType<PL_XService>().As<IXService>().InstancePerHttpReques‌​t();

Categories