Currently I am using Unity 3.x as my IoC. I also using the Unity.MVC4 library to help manage the lifetime of my resolver. Here is what my resolver looks like:
namespace Wfm.Core.Common.Mvc.Unity
{
public class WfmDependencyResolver : UnityDependencyResolver
{
public WfmDependencyResolver(IUnityContainer container) : base(container)
{
}
private static WfmDependencyResolver _wfmGrabbrResolver;
public static WfmDependencyResolver Instance { get { return _wfmGrabbrResolver ?? (_wfmGrabbrResolver = new WfmDependencyResolver(InstanceLocator.Instance.Container)); } }
}
}
The UnityDependencyResolver comes from the Unity.MVC4 library. In my Globabl.asax.cs file I am setting the resolver like this:
DependencyResolver.SetResolver(WfmDependencyResolver.Instance);
Here is my singleton InstanceLocator class:
public class InstanceLocator
{
private static InstanceLocator _instance;
public IUnityContainer Container { get; private set; }
private InstanceLocator()
{
Container = new UnityContainer();
}
public static InstanceLocator Instance
{
get { return _instance ?? (_instance = new InstanceLocator()); }
}
public T Resolve<T>()
{
try
{
return WfmDependencyResolver.Instance.GetService<T>();
}
catch(Exception ex)
{
return default(T);
}
}
public T ResolvewithoutManager<T>()
{
try
{
return Container.Resolve<T>();
}
catch (Exception)
{
throw;
}
}
}
This obviously works well from my MVC controllers, but what would be a good solution to allow my application to resolve inside my Hub controllers along with my MVC controllers. Currently, I created a singleton class that allows me to resolve my types manually. I can specifically resolve my types inside my Hubs using my the class like this:
InstanceLocator.Instance.Resolve<ISomeInterface>();
While this works, its not ideal from a development standpoint. Reason being, I want my types to be injected and not manually instantiated. My hubs and Controllers are inside the same MVC application and I do not want to have separate them right now.
There's an entire article devoted to dependency injection in SignalR: http://www.asp.net/signalr/overview/extensibility/dependency-injection
So all you have to do is write a custom dependency resolver for SignalR which obviously will be a simple wrapper to your commonly shared Unity container.
Related
I am working with Asp.Net Core application. I have two classes namely Online and Offline. I have created interface and defined the methods in these two classes. Based on the need I have to connect to anyone of these two classes.
Previously when I worked in Asp.Net MVC, I have used unity container and Service Locator to specify the class name in XML file for invoking the class dynamically (between online and offline).
Now I want to implement the same with Asp.Net core. But I am not sure how to specify the class name outside for method invocation. Kindly help.
Thanks
In .net core dependency injection is in built. You don't need unity or any other any more.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0
You can achieve what you want by using a little tweak.
//// classes
public interface IFileUploadContentProcess
{
IEnumerable<StoreOrder> ProcessUploads(IFormFile file);
}
public class ProcessExcelFiles : IFileUploadContentProcess
{
public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
{
throw new NotImplementedException();
}
}
public class ProcessCsvFiles : IFileUploadContentProcess
{
public IEnumerable<StoreOrder> ProcessUploads(IFormFile file)
{
throw new NotImplementedException();
}
}
//// register it
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<IStoreOrderService, StoreOrderService>();
services.AddTransient<ProcessExcelFiles>();
services.AddTransient<ProcessCsvFiles>();
// Add resolvers for different sources here
services.AddTransient<Func<string, IFileUploadContentProcess>>(serviceProvider => key =>
{
return key switch
{
"xlsx" => serviceProvider.GetService<ProcessExcelFiles>(),
_ => serviceProvider.GetService<ProcessCsvFiles>(),
};
});
}
//use it
public class StoreOrderService : IStoreOrderService
{
private readonly Func<string, IFileUploadContentProcess> _fileUploadContentProcess;
public StoreOrderService(Func<string, IFileUploadContentProcess> fileUploadContentProcess)
{
_fileUploadContentProcess = fileUploadContentProcess;
}
public async Task<IEnumerable<StoreOrder>> UploadStoreOrdersAsync(IFormFile file)
{
//// passing csv to process csv type(default), if xlsx, pass xlsx
var records = _fileUploadContentProcess("csv").ProcessUploads(file);
return records;
}
}
After lot of brainstroming, I found the below solution
Create a class for ServiceLocator
public class ServiceLocator
{
private ServiceProvider _currentServiceProvider;
private static ServiceProvider _serviceProvider;
public ServiceLocator(ServiceProvider currentServiceProvider)
{
_currentServiceProvider = currentServiceProvider;
}
public static ServiceLocator Current
{
get
{
return new ServiceLocator(_serviceProvider);
}
}
public static void SetLocatorProvider(ServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public object GetInstance(Type serviceType)
{
return _currentServiceProvider.GetService(serviceType);
}
public TService GetInstance<TService>()
{
return _currentServiceProvider.GetService<TService>();
}
}
Step 2: Create interface and inherit in the classes and define the interface methods
Step 3: Define class name in appSettings.json and read the values in startup.cs
public void ConfigureServices(IServiceCollection services)
{
//reading from appSettings.json
string strClassName = Configuration["DependencyInjection:className"];
if (strClassName == "OnlineData")
services.AddTransient<<<InterfaceName>>, <<OnlineClassName>>>();
if (strClassName == "OfflineData")
services.AddTransient<<<InterfaceName>>, <<OfflineClassName>>>();
}
Step 4: Create object for the dynamic class inside controller/action method
InterfaceNamemyService = ServiceLocator.Current.GetInstance<>();
I've created a web api core 2.0 application.
I've got my main app and the Business Layer.
I want to place the automapper profile in the business layer so that all the mappings are made in the business layer. My business layer is just a class library project.
Is this possible? or do I need to place all my mapping in a Profile class in the main app?
Just a theoretical explanation can help.
Yes, it's possible but it depends on where the model classes reside.
You can give each layer or project a Profile where you map the appropriate model classes. Then in the project where you want to use the mapper, create the ObjectMapper class to load the Profiles.
namespace BL.Config
{
public class MapperProfile : Profile
{
public MapperProfile()
{
CreateMap<Entity, Dto>();
...
}
}
public class ObjectMapper
{
public static IMapper Mapper
{
get { return mapper.Value; }
}
public static IConfigurationProvider Configuration
{
get { return config.Value; }
}
public static Lazy<IMapper> mapper = new Lazy<IMapper>(() =>
{
var mapper = new Mapper(Configuration);
return mapper;
});
public static Lazy<IConfigurationProvider> config = new Lazy<IConfigurationProvider>(() =>
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<BL.Config.MapperProfile>();
cfg.AddProfile<AppCore.Config.MapperProfile>(); // any other profiles you need to use
});
return config;
});
}
}
When I need to use AutoMapper, I use the ObjectMapper.Mapper to get my mapper instance. I like to add this to an abstract service.
public interface IAutoMapperService
{
IMapper Mapper { get; }
}
public abstract class AutoMapperService : IAutoMapperService
{
public IMapper Mapper
{
get { return BAL.Config.ObjectMapper.Mapper; }
}
}
And usage: The service has the Mapper member.
public class SomeService : AutoMapperService, ISomeService
{
public Foo GetFoo()
{
var foo = Mapper.Map<Foo>(bar);
return foo;
}
}
Or just implement the IAutoMapperService if you can't inherit another base class.
The downside is BL requires the AutoMapper dependency. But using this way I find I can hide many models from the other layers.
I am having one Application based on XamarinForms.
One background service I have created in Android project and that service would like to send data to ContentPage(which is in PCL) which is displayed to user.
How could I pass data to ContentPage(From xx.Droid project to PCL)?
One solution is:
To Create class in PCL with static variable(e.g. var TEMP_VAR), which will be accessed from xxx.Droid project.
Update value of that static variable(TEMP_VAR) from the service class from the xxx.Droid project.
Need to create Notifier on that static variable(TEMP_VAR)
Update the content page using MessageCenter Mechanism if require.
If there is any better solution, could you please provide me?
This can be achieved using the concept of C#
Dependency service
Event
Need to have 4 classes for such an implementation:
Interface in PCL(e.g. CurrentLocationService.cs) with event handlers defined in it.
namespace NAMESPACE
{
public interface CurrentLocationService
{
void start();
event EventHandler<PositionEventArgs> positionChanged;
}
}
Implementation of interface of PCL in xxx.Droid project (e.g. CurrentLocationService_Android.cs) using Dependency service
class CurrentLocationService_Android : CurrentLocationService
{
public static CurrentLocationService_Android mySelf;
public event EventHandler<PositionEventArgs> positionChanged;
public void start()
{
mySelf = this;
Forms.Context.StartService(new Intent(Forms.Context, typeof(MyService)));
}
public void receivedNewPosition(CustomPosition pos)
{
positionChanged(this, new PositionEventArgs(pos));
}
}
ContentPage in PCL - which will have object of implementation of interface.
Object can be obtained by
public CurrentLocationService LocationService
{
get
{
if(currentLocationService == null)
{
currentLocationService = DependencyService.Get<CurrentLocationService>();
currentLocationService.positionChanged += OnPositionChange;
}
return currentLocationService;
}
}
private void OnPositionChange(object sender, PositionEventArgs e)
{
Debug.WriteLine("Got the update in ContentPage from service ");
}
Background service in xxx.Droid project. This service will have reference of implementation of dependency service CurrentLocationService.cs
[Service]
public class MyService : Service
{
public string TAG = "MyService";
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
Log.Debug(TAG, TAG + " started");
doWork();
return StartCommandResult.Sticky;
}
public void doWork()
{
var t = new Thread(
() =>
{
Log.Debug(TAG, "Doing work");
Thread.Sleep(10000);
Log.Debug(TAG, "Work completed");
if(CurrentLocationService_Android.mySelf != null)
{
CustomPosition pos = new CustomPosition();
pos.update = "Finally value is updated";
CurrentLocationService_Android.mySelf.receivedNewPosition(pos);
}
StopSelf();
});
t.Start();
}
}
Note : PositionEventArgs class need to be created as per usage to pass on data between service and ContentPage.
This works for me like charm.
Hope so this would be helpful to you.
I am preparing a ReSTful service which I would like to have documented using RAML (and perhaps Swagger as well), but it seems that I cannot implement both JAX-RS and RAML in the same application at the same time.
I have created an Application class for JAX-RS as follows:
public class Application extends javax.ws.rs.core.Application {
#Override
public Set<Class<?>> getClasses() {
// Use the reflections library to scan the current package tree for
// classes annotated with javax.ws.rs.Path and add them to the JAX-RS
// application
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
return reflections.getTypesAnnotatedWith(Path.class);
}
}
I attach the JAX-RS Application object as follows:
Component component = new Component();
Server server = new Server(Protocol.HTTP, PORT);
component.getServers().add(server);
JaxRsApplication jaxRsApplication = new JaxRsApplication(component.getContext().createChildContext());
jaxRsApplication.add(new Application());
jaxRsApplication.setObjectFactory(objectFactory);
component.getDefaultHost().attach("/rest", jaxRsApplication);
And I would also like to implement the RAML extension, but it looks like it is tied to the Restlet Router and having it's own Application class. Is there a way to combine the two?
Indeed the RAML extension of Restlet isn't designed to be used within JAXRS application. That said you can define a resource that provide the RAML content based on classes ApplicationIntrospector of Restlet and RamlEmitter of RAML parser, as described below:
public class RamlResource {
private Definition definition;
#Path("/raml")
#GET
public String getRaml() {
return new RamlEmitter().dump(RamlTranslator
.getRaml(getDefinition()));
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (RamlResource.class) {
definition = ApplicationIntrospector.getDefinition(
Application.getCurrent(),
new Reference("/"), null, false);
}
}
return definition;
}
}
It's the way the RAML extension of Restlet works. You could also use such an approach for Swagger but be careful since Swagger 1.2 requires several resources (a main and several sub ones with each categories). It's not the case anymore for Swagger 2.
You can notice that there is a JAX-RS support for Swagger in the extension org.restlet.ext.swagger.
----- Edited
Perhaps can you make a try with this class that corresponds to a port of the class JaxRsApplicationSwaggerSpecificationRestlet to RAML. It's based on the class JaxRsIntrospector which seems relevant for JAX-RS application:
public class JaxRsApplicationRamlSpecificationRestlet extends Restlet {
private Application application;
private String basePath;
private Reference baseRef;
private Definition definition;
public JaxRsApplicationRamlSpecificationRestlet(Application application) {
this(null, application);
}
public JaxRsApplicationRamlSpecificationRestlet(Context context, Application application) {
super(context);
this.application = application;
}
public void attach(Router router) {
attach(router, "/api-docs");
}
public void attach(Router router, String path) {
router.attach(path, this);
router.attach(path + "/{resource}", this);
}
public Representation getApiDeclaration() {
Raml raml = RamlTranslator.getRaml(
getDefinition());
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
return new StringRepresentation(
mapper.writeValueAsString(raml),
MediaType.APPLICATION_YAML);
} catch (Exception ex) {
return new StringRepresentation("error");
}
}
public String getBasePath() {
return basePath;
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (JaxRsApplicationRamlSpecificationRestlet.class) {
definition = JaxRsIntrospector.getDefinition(application,
baseRef, false);
}
}
return definition;
}
#Override
public void handle(Request request, Response response) {
super.handle(request, response);
if (Method.GET.equals(request.getMethod())) {
response.setEntity(getApiDeclaration());
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
}
public void setApiInboundRoot(Application application) {
this.application = application;
}
public void setApplication(Application application) {
this.application = application;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
// Process basepath and check validity
this.baseRef = basePath != null ? new Reference(basePath) : null;
}
}
You can use this class like this:
JaxRsApplication application
= new JaxRsApplication(component.getContext());
MyApplication app = new MyApplication();
application.add(app);
new JaxRsApplicationRamlSpecificationRestlet(app);
(...)
There is no need for a dedicated resource. Please note that this code is a bit experimental ;-) I could propose it back for a contribution for the extension raml in Restlet...
Hope it helps you,
Thierry
I'm building an application which uses AutoFac 2 for DI. I've been reading that using a static IoCHelper (Service Locator) should be avoided.
IoCHelper.cs
public static class IoCHelper
{
private static AutofacDependencyResolver _resolver;
public static void InitializeWith(AutofacDependencyResolver resolver)
{
_resolver = resolver;
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
}
From answers to a previous question, I found a way to help reduce the need for using my IoCHelper in my UnitOfWork through the use of Auto-generated Factories. Continuing down this path, I'm curious if I can completely eliminate my IoCHelper.
Here is the scenario:
I have a static Settings class that serves as a wrapper around my configuration implementation. Since the Settings class is a dependency to a majority of my other classes, the wrapper keeps me from having to inject the settings class all over my application.
Settings.cs
public static class Settings
{
public static IAppSettings AppSettings
{
get
{
return IoCHelper.Resolve<IAppSettings>();
}
}
}
public interface IAppSettings
{
string Setting1 { get; }
string Setting2 { get; }
}
public class AppSettings : IAppSettings
{
public string Setting1
{
get
{
return GetSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return GetSettings().AppSettings["setting2"];
}
}
protected static IConfigurationSettings GetSettings()
{
return IoCHelper.Resolve<IConfigurationSettings>();
}
}
Is there a way to handle this without using a service locator and without having to resort to injecting AppSettings into each and every class? Listed below are the 3 areas in which I keep leaning on ServiceLocator instead of constructor injection:
AppSettings
Logging
Caching
I would rather inject IAppSettings into every class that needs it just to keep them clean from the hidden dependency on Settings. Question is, do you really need to sprinkle that dependency into each and every class?
If you really want to go with a static Settings class I would at least try to make it test-friendly/fakeable. Consider this:
public static class Settings
{
public static Func<IAppSettings> AppSettings { get; set; }
}
And where you build your container:
var builder = new ContainerBuilder();
...
var container = builder.Build();
Settings.AppSettings = () => container.Resolve<IAppSettings>();
This would allow to swap out with fakes during test:
Settings.AppSettings = () => new Mock<IAppSettings>().Object;
Now the AppSettings class (which I assume there is only one of) you could do with regular constructor injection. I assume also that you really want to do a resolve on each call to your settings properties, thus injecting a factory delegate that retrieves an instance when needed. If this is not needed you should of course inject the IConfigurationSettings service directly.
public class AppSettings : IAppSettings
{
private readonly Func<IConfigurationSettings> _configurationSettings;
public AppSettings(Func<IConfigurationSettings> configurationSettings)
{
_configurationSettings = configurationSettings;
}
public string Setting1
{
get
{
return _configurationSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return _configurationSettings().AppSettings["setting2"];
}
}
}