Passing a unique value to all classes using Dependency Injection? - c#

The following code shows the flow I’m currently trying to implement within a WCF service. The service on startup calls the Bootstrapper class which uses Unity to register and resolve the required types. The Gateway class contains the public method which then kicks off the main flow of processing a message (there are many more levels to the code than is shown below).
public static class Bootstrapper
{
public static IGateway InitializeGateway()
{
IUnityContainer resolver = new UnityContainer();
resolver.RegisterType<IGateway, Gateway>();
resolver.RegisterType<ITranslator, Translator>();
resolver.RegisterType<IFormatter, IFormatter>();
return resolver.Resolve<IGateway>();
}
}
public class Gateway : IGateway
{
private readonly ITranslator translator;
private readonly IFormatter formatter;
public Gateway(ITranslator translator, IFormatter formatter)
{
this.translator = translator;
this.formatter = formatter;
}
public string ProcessMessage(string requestMessage)
{
// Create a new GUID for use in main flow for logging
Guid messageGuid = Guid.NewGuid();
requestMessage = this.translator.TranslateMessage(requestMessage);
requestMessage = this.formatter.FormatMessage(requestMessage);
return requestMessage;
}
}
Now what I’m trying to achieve is take the GUID (created for each message) and pass this down within the flow of the service such that each class has a reference to it for logging purposes.
I have tried to find a way of using DI and constructor injection but don’t know if this can be done as the GUID is created on receipt of a message by the gateway (after the bootstrapper call). What I’m trying to get away from is passing the GUID into each method as a parameter.
Any suggestions?

Instead of rolling your own solution to this problem with DI, I would recommend you use the thread-static property Trace.CorrelationManager.ActivityId for this purpose.
Take a look at this article on WCF End-To-End Tracing.

Related

Adding helper class which uses "IHttpContextAccessor" should be Singlton or Scoped

I am creating a class which reads the header using IHttpContextAccessor and reads the values from header.
Like ".net framework" we can access context in static manner HttpContext.Current... so shall I inject my class as Singlton or Scoped as the context or context.header value is going to change in each request.
Below is what I am trying
public class RequestHeaderHelper
{
private readonly IHttpContextAccessor httpContext;
public RequestHeaderHelper(IHttpContextAccessor httpContext)
{
this.httpContext = httpContext;
}
public string BrowserIP
{
get
{
if (httpContext.HttpContext.Request.Headers.ContainsKey("X-Client-IP"))
return httpContext.HttpContext.Request.Headers.ContainsKey("X-Client-IP").ToString();
else
return string.Empty;
}
private set { }
}
....
}
Edit 1
Further I am going to use this class inside my other classes like logger. I have created action filter and exception logger where I am going to use this.
I am also using wcf client class to call the service. I am using logging there as well using beforesend and aftersend. I am adding endpoint behavior.
I want to use wcf client as singlton but use the above class in logger.

Dependency Injection with classes other than a Controller class

At this point I'm injecting things into my Controllers with ease, in some cases building my own ResolverServices class. Life is good.
What I cannot figure out how to do is get the framework to automatically inject into non-controller classes. What does work is having the framework automatically inject into my controller IOptions, which is effectively the configuration for my project:
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
public MessageCenterController(IOptions<MyOptions> options)
{
_options = options.Value;
}
}
I'm thinking whether I can do the same for for my own classes. I assume I'm close when I mimic the controller, like this:
public class MyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
}
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
I think where I'm failing is when I call it like this:
public void DoSomething()
{
var helper = new MyHelper(??????);
if (helper.CheckIt())
{
// Do Something
}
}
The problem I have tracking this down is practically everything that talks about DI is talking about it at the controller level. I tried hunting down where it happens in the Controller object source code, but it gets kinda crazy in there.
I do know I can manually create an instance of IOptions and pass it to the MyHelper constructor, but it seems like I should be able to get the framework do that since it works for Controllers.
Below is a working example of using DI without anything that involves MVC Controllers. This is what I needed to do to understand the process, so maybe it will help somebody else.
The ShoppingCart object gets, via DI, an instance of INotifier (which notifies the customer of their order.)
using Microsoft.Extensions.DependencyInjection;
using System;
namespace DiSample
{
// STEP 1: Define an interface.
/// <summary>
/// Defines how a user is notified.
/// </summary>
public interface INotifier
{
void Send(string from, string to, string subject, string body);
}
// STEP 2: Implement the interface
/// <summary>
/// Implementation of INotifier that notifies users by email.
/// </summary>
public class EmailNotifier : INotifier
{
public void Send(string from, string to, string subject, string body)
{
// TODO: Connect to something that will send an email.
}
}
// STEP 3: Create a class that requires an implementation of the interface.
public class ShoppingCart
{
INotifier _notifier;
public ShoppingCart(INotifier notifier)
{
_notifier = notifier;
}
public void PlaceOrder(string customerEmail, string orderInfo)
{
_notifier.Send("admin#store.com", customerEmail, $"Order Placed", $"Thank you for your order of {orderInfo}");
}
}
public class Program
{
// STEP 4: Create console app to setup DI
static void Main(string[] args)
{
// create service collection
var serviceCollection = new ServiceCollection();
// ConfigureServices(serviceCollection)
serviceCollection.AddTransient<INotifier, EmailNotifier>();
// create service provider
var serviceProvider = serviceCollection.BuildServiceProvider();
// This is where DI magic happens:
var myCart = ActivatorUtilities.CreateInstance<ShoppingCart>(serviceProvider);
myCart.PlaceOrder("customer#home.com", "2 Widgets");
System.Console.Write("Press any key to end.");
System.Console.ReadLine();
}
}
}
Let's say MyHelper is used by MyService which in turn is used by your controller.
The way to resolve this situation is:
Register both MyService and MyHelper in Startup.ConfigureServices.
services.AddTransient<MyService>();
services.AddTransient<MyHelper>();
The controller receives an instance of MyService in its constructor.
public HomeController(MyService service) { ... }
MyService constructor will in turn receive an instance of MyHelper.
public MyService(MyHelper helper) { ... }
The DI framework will be able resolve the whole object graph without problems. If you are worried about new instances being created every time an object is resolved, you can read about the different lifetime and registration options like the singleton or request lifetimes.
You should be really suspicious when you think you have to manually create an instance of some service, as you might end up in the service locator anti-pattern. Better leave creating the objects to the DI Container. If you really find yourself in that situation (let's say you create an abstract factory), then you could use the IServiceProvider directly (Either request an IServiceProvider in your constructor or use the one exposed in the httpContext).
var foo = serviceProvider.GetRequiredService<MyHelper>();
I would recommend reading the specific documentation about the ASP.Net 5 DI framework and about dependency injection in general.
Unfortunately there is no direct way. The only way I managed to make it work is by creating a static class and using that everywhere else as below:
public static class SiteUtils
{
public static string AppName { get; set; }
public static string strConnection { get; set; }
}
Then in your startup class, fill it in as below:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//normal as detauls , removed for space
// set my variables all over the site
SiteUtils.strConnection = Configuration.GetConnectionString("DefaultConnection");
SiteUtils.AppName = Configuration.GetValue<string>("AppName");
}
Although this is bad pattern, as this will stay for the whole life cycle of the application and I couldn't find better way to use it outside controller.
Here's a more complete example to directly answer the OP's question, based on the current .NET Core 2.2 DI documentation here. Adding this answer since it may help someone that's new to .NET Core DI, and because this question is Google's top search result.
First, add an interface for MyHelper:
public interface IMyHelper
{
bool CheckIt();
}
Second, update the MyHelper class to implement the interface (in Visual Studio, press ctrl-. to implement the interface):
public class MyHelper : IMyHelper
{
private readonly ProfileOptions _options;
public MyHelper(IOptions<ProfileOptions> options)
{
_options = options.Value;
{
public bool CheckIt()
{
return _options.SomeBoolValue;
}
}
Third, register the interface as a framework-provided service in the DI service container. Do this by registering the IMyHelper service with the concrete type MyHelper in the ConfigureServices method in Startup.cs.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IMyHelper, MyHelper>();
...
}
Fourth, create a private variable to reference an instance of the service. Pass the service as an argument in the constructor (via constructor injection) then initialize the variable with the service instance. Reference any properties or call methods on this instance of the custom class via the private variable.
public class MessageCenterController : Controller
{
private readonly MyOptions _options;
private readonly IMyHelper _myHelper;
public MessageCenterController(
IOptions<MyOptions> options,
IMyHelper myHelper
)
{
_options = options.value;
_myHelper = myHelper;
}
public void DoSomething()
{
if (_myHelper.CheckIt())
{
// Do Something
}
}
}
You may use Activator.CreateInstance(). Here is a wrapper function for it. The way you use this is as follows.
var determinedProgrammatically = "My.NameSpace.DemoClass1"; // implements IDemo interface
var obj = CreateInstance<My.NameSpace.IDemo, string>(determinedProgrammatically, "This goes into the parameter of the constructor.", "Omit this parameter if your class lives in the current assembly");
Now you have an instance of obj which is instantiated from type determined programmatically. This obj can be injected into non controller classes.
public TInterface CreateInstance<TInterface, TParameter>(string typeName, TParameter constructorParam, string dllName = null)
{
var type = dllName == null ? System.Type.GetType(typeName) :
System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith(dllName, System.StringComparison.OrdinalIgnoreCase)).GetType(typeName);
return (TInterface)System.Activator.CreateInstance(type, constructorParam);
}
PS: You may iterate through System.AppDomain.CurrentDomain.GetAssemblies() to determine the name of the assembly that houses your class. This name is used in the 3rd parameter of the wrapper function.
TL;DR: You can save a singleton in a static var and then access it form other classes, but this an anti-pattern, use with caution.
Long version:
As per this question Resolving instances with ASP.NET Core DI from within ConfigureServices
Any services registered in ConfigureServices() can then be injected
into the Configure() method
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<FooService>();
}
public void Configure(IApplicationBuilder app, FooService fooService)
{
FooServiceInstance = fooService;
}
public static FooService FooServiceInstance { get; private set; }
And then call it from your other code MyStartupClass.FooService.DoStuff()

Autofac WCF Integration - Resolve dependencies based on request data

How can I configure an Autofac container so it resolves the dependencies of a WCF service based on properties values of the operation-parameter (request object)?
For example, given this data contract...
[DataContract]
public class MyRequest
{
[DataMember]
public bool MyBool { get; set; }
}
this WCF service...
public class MyWcfService : IWcfService
{
private IService m_service;
public MyWcfService(IService service)
{
m_service = service;
}
public virtual MyResponse Operation(MyRequest request) { }
}
and these dependencies...
public interface IService { }
public class TypeA : IService { }
public class TypeB : IService { }
I would like the container to resolve TypeA if MyBool equals true and TypeB otherwise. Is that feature available? Should I approach the problem differently?
Constraints:
Avoiding the Autofac.Extras.Multitenant package is a plus.
Keeping the signature of the service constructor unchanged is also desired. (See my answer below)
There are a few ways to achieve this. One of the ways is to use IIndex<K,V>. It's built-in "lookup" feature that chooses between service implementations based on a key. You can find more info on Autofac's wiki page. An example code could look like:
// Register your dependency with a key, for example a bool flag
builder.RegisterType<TypeA>().Keyed<IService>(true);
builder.RegisterType<TypeB>().Keyed<IService>(false);
// Your service could look like:
public class MyWcfService
{
private readonly IIndex<bool, IService> _services;
// Inject IIndex<Key,Value> into the constructor, Autofac will handle it automatically
public MyWcfService(IIndex<bool, IService> services)
{
_services = services;
}
public virtual void Operation(MyRequest request)
{
// Get the service that you need by the key
var service = _services[request.MyBool];
}
}
Another approach is to use Metadata feature. More information on wiki page.
Option 1 - Using Autofac:
The Autofac instance provider that creates your service instance does not use or pass along the operation's message. Here's the latest implementation of the method in Autofac. Notice the message parameter is unused.
public class AutofacInstanceProvider : IInstanceProvider
{
// lots of code removed...
public object GetInstance(InstanceContext instanceContext, Message message)
{
if (instanceContext == null)
{
throw new ArgumentNullException("instanceContext");
}
var extension = new AutofacInstanceContext(_rootLifetimeScope);
instanceContext.Extensions.Add(extension);
return extension.Resolve(_serviceData);
}
}
So to get the behavior you want with existing Autofac code, you'll need to inject the dependency into your class using something other than constructor injection, which is #Alexandr Nikitin's solution. This is reasonable, but I agree with the comment "not loving it".
Option 2 - A Custom IInstanceProvider:
Writing a custom WCF IInstanceProvider is a reasonable option, but it will be a lot of code.
The good news is that the code in Autoface.Integration.WCF is a nice example and you could plug your implementation into Autofac.
The bad news is that Autofac.Integration.WCF code doesn't itself use dependency injection. For example AutofacDependencyInjectionServiceBehavior directly calls var instanceProvider = new AutofacInstanceProvider(_rootLifetimeScope, _serviceData). As a result you'll you have to implement a replacement for AutofacInstanceProvider, AutofacDependencyInjectionServiceBehavior, AutofacHostFactory, and probably more. Then you'll need to create an extension for the AutofacInstanceContext to contain the information read from the message. Its a lot of code.
If you are going to do the custom IInstanceProvider I suggest reading up on Carlos Figueira's blog:
WCF Extensibility – IInstanceProvider - for good background
WCF Extensibility – Message Inspectors - Search for the section that starts with WCF Message objects can only be “consumed once". You'll need to follow these rules when inspecting the message.

How to specify the implementation you want to inject

I'm in the process of implementing a notification service. Essentially, customers can get notified in a number of ways, such as via email, text message, fax etc. Below is a rough implementation that is not wired together.
public class NotificationService
{
private readonly INotification _notification;
private readonly INotificationFormatter _formatter;
public NotificationService(
INotificationMethod notification,
INotificationFormatter formatter)
{
_notification = notification;
_formatter = formatter;
}
public void Notify(SomeParameterObject obj)
{
var formattedMessage = _formatter.Format(obj);
_notification.SendNotification(formattedMessage);
}
}
public interface INotificationFormatter
{
NotificationMessage Format(SomeParameterObject obj);
}
public interface INotification
{
void SendNotification();
}
public EmailNotification : INotification
{
public void SendNotification(NotificationMessage message)
{
// Use Exchange Web Services to send email
}
}
The NotificationService class essentially takes in a method of notification and a formatter. Obviously, each method of notification requires different formatting.
Based on business criteria, how do I select which implementation of INotification and NotificationFormatter I wish to use? Note that within the lifetime of the user using the application each notification will most likely be used. I say this because it's not as simple as instructing my container to inject implementation Foobar as it will change while the user is using the application.
I've thought of creating some sort of class that could handle pairs because it seems to makes sense to me that you wouldn't want use a text message notification formatter for a fax notification. However, I can't seem to wrap my head around a decent implementation of this.
I also own the book Dependency Injection in .NET by Mark Seemann. Did I perhaps miss something obvious?
Thank you.
How is it that you decide what kind of notification a user wants? If it can change while they're using your app, it seems like the NotificationService for that user msut be created anew for each notification you want to send them. That's ok - just use some sort of lookup to select a INotification impelmentation with an IoC container.
IoC's (I use AutoFac) let you use string-indexes to select a specific implementation. That string could come from a DB or whatever to represent the user's preference. Then you'd pass it to your IoC asking for an INotification 'decorated' with your string-choice. Upon startup, all the various implementations are registered with thier choice-strings.
I think you may be on to something with your 'pairs' comment - if INotificationFormat is closely tied to INotification and there is a possiblity of mixing them up then perhaps the INotification implementation itself should select its formatter.
What you need to do is to provide some kind of configuration infrastructure. For example, assuming that you want to keep the service just the way you've defined it, I would implement a factory returning an instance of NotificationService according to your model:
public struct NotificaitonSettings<T>
{
public Predicate<T> Predicate;
public NotificationService Service;
}
public class NotificationServiceFactory<T> : INotificationServiceFactory<T>
{
protected static List<NotificaitonSettings<T>> settings = new List<NotificaitonSettings<T>>();
static NotificationServiceFactory()
{
settings.Add(new NotificaitonSettings<T>
{
Predicate = m => !String.IsNullOrEmpty(m.Email),
Service = new NotificationService(new EmailNotification(), new EmailFormatter())
});
settings.Add(new NotificaitonSettings<T>
{
Predicate = m => !String.IsNullOrEmpty(m.Fax),
Service = new NotificationService(new FaxNotification(), new FaxFormatter())
});
}
public NotificationService Create(T model)
{
return settings.FirstOrDefault(s => s.Predicate(model)).Service;
}
}
This implementation configures the factory using static list, you could use a IoC container if it supports this kind of operations.

using ninject with a remoting server

I have a class Server that implements interface IServer that is accessible using .net remoting (i have no chioce on the matter JICYAW).
internally this server uses other classes to implement logic and data access.
this server class has constructor injected dependencies that it needs to do its job.
when a client calls in (per call) the remoting framework will instatiate a Server instance using a parameterless constructor and not (of course) using Ninject.
how can i get Ninject to be the one in charge for new'ing up the class ?
i have seen this similar SO question but this isnt relevant for Ninject.
thanks for your help
You can create a service facade that will be called by the client. This facade will internally call your container to resolve the real service. For instance:
public class ServiceFacade : IService
{
private readonly IService service;
// default constructor
public ServiceFacade()
{
this.service = YourContainer.Current.Resolve<IService>();
}
void IService.ServiceOperation()
{
this.service.ServiceOperation();
}
}
What might work is to intercept the calls to those objects using a proxy and forward the calls to the real object. Note that I'm not very experienced with this, so I'm not sure if this actually works, but here goes:
public class DependencyInjectionProxy : RealProxy
{
private object realInstance;
public DependencyInjectionProxy(Type classToProxy,
object realInstance) : base(classToProxy)
{
this.realInstance = realInstance;
}
public static T MakeProxy<T>(T realInstance)
{
return (T)(new DependencyInjectionProxy(typeof(T),
realInstance).GetTransparentProxy());
}
public override IMessage Invoke(IMessage msg)
{
if (msg is IMethodCallMessage)
{
var message = (IMethodCallMessage)msg;
object value = message.MethodBase.Invoke(
this.realInstance, message.Args);
Console.WriteLine(value);
return new ReturnMessage(value, null, 0, null, message);
}
return msg;
}
}
This works when you do something like this:
var container = new YourContainer();
container.RegisterSingle<IService, Service>();
IService proxy = DependencyInjectionProxy.MakeProxy<IService>(
container.Resolve<IService>());
proxy.SomeMethod();
This works great, but to be honest, I have no idea how to configure this in a way that you can intercept incoming calls this way. Somewhere you need to register your DependencyInjectionProxy, but that's where my experience with remoting stops :-)

Categories