I'm trying to implement web application and using a singleton object so I would be able to inject it to use it in other classes.
I want to open a new object every time the user opens a tab or similar in the browser. For example:
public class Singleton
{
public string Id{get;set;}
public Singleton(){Id=Guid.NewGuid().ToString();)
}
in startup:
services.AddSingleton<Singleton>(s=>new Singleton());
In some other class:
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(Singleton singleton)
{
this.singleton = singleton;
}
}
The problem is that every tab has the same Id... I need a different id for every tab in the browser...
Thanks!
You have to make an Interface for the class you want to be a singleton. You register it in your Startup.cs as a Singleton
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISingleton, Singleton>();
}
You then proceed to inject the singleton interface into OtherClass
public class OtherClass{
private readonly Singleton singleton;
public OtherClass(ISingleton singleton)
{
this.singleton = singleton;
}
Hope this helps
Ok I've found some solution....
I'm creating a singleton class that has an object that will change ...
When I want to change the object details, I do this in a method...
Then I have the updated information for all the WebApp.
The change will be made in every method that I need to specify the object details...
For example:
public class InjectedSingleton
{
public MySession CurrentSession{get;set;}
public void SetSession(string sessionId)
{
CurrentSession = GetSessionById(sessionId);
}
public void NewSession()
{
CurrentSession = new MySession();
}
}
public class DoClass
{
private InjectedSingleton inj;
public DoClass(InjectedSingleton inj)
{
this.inj = inj;
}
public void OpenNewTab(string sessionId)
{
inj.SetSession(sessionId);
}
public void JustShowSomething()
{
Show(inj.CurrentSession.Id);
}
}
Now, the updated session is the required one, for everywhere in the app for the current user
Related
We are building an application where we have to have both old and new version to work side by side (V1 is old and V2 is new). Now to handle new flow we are using same old interfaces with everything being the same and differs only in functionality, hence now we have to define a named instance in-order to resolve the instances for new flow.
In the process teams have started using Service Factory Pattern as shown below
class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IServiceFactory serviceFactory)
{
_dataManager = serviceFactory.GetInstance<IDataManager>();
}
public void Execute()
{
_dataManager.Run();
}
}
Service Factory Class
public class ServiceFactory : IServiceFactory
{
private readonly IFeatureEvaluator _featureEvaluator;
public ServiceFactory(IFeatureEvaluator featureEvaluator)
{
_featureEvaluator = featureEvaluator;
}
public T GetInstance<T>()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
return ObjectFactory.GetInstance<T>("V2")
}
return ObjectFactory.GetInstance<T>();
}
}
Since Service Factory is anti-pattern and also it creates lot of complexities in retiring the old flow in future, I would want a way to initialize the dependencies at the container(structuremap ioc) itself or to work in a "Pure DI" way so that we can avoid headache. Any idea on how to tackle this.
Update:
IDataManager Implementation
public interface IDataManager
{
void Run();
}
public class OldFlow : IDataManager
{
public void Run()
{
//
}
}
public class NewFlow : IDataManager
{
public void Run()
{
//
}
}
IDataManager has 2 implementations and resolving the instance should be based on _featureEvaluator, if V2 flow then "newflow" should be instantiated else "old flow" instance
Why don't you just inject the dependency you need?
public class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IDataManager dataManager)
{
_dataManager = dataManager;
}
public void Execute()
{
_dataManager.Run();
}
}
In your Composition Root you can conditionally compose DataProcessor with the implementation of IDataManager you'd like:
public DataProcessor CreateDataProcessor()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
IDataManager dm = new NewFlow();
return new DataProcessor(dm);
}
IDataManager dm = new OldFlow();
return new DataProcessor(dm);
}
This seems to be similar to feature toggles. Why, by the way, is _featureEvaluator an interface? Wouldn't a bool suffice?
Im considering, whether class which gonna communicate with database should be a singleton.
Instead of injecting context everywhere it's needed, I've created one inside Database class, which is the singleton class.
Is it good practice?
Code:
class DatabaseService
{
public FreelanceOrganizerDataContext DatabaseContext { get; private set; } = new FreelanceOrganizerDataContext();
static DatabaseService _singleton = new DatabaseService();
private DatabaseService() { }
public static DatabaseService GetDatabaseService()
{
return _singleton;
}
//Save Section
public void AddProject()
{
}
public void AddCustomer()
{
}
//etc
}
I would recommend using an IoC such as Unity or Autofac. You can do things such as Inject Dependecies into your classes, control the lifecycle of the objects (when and how often they are instantiated), and better set yourself up for Unit Tests.
I am having to re-write a large WinForms application and I want to use MVC to allow increased testing capability etc. I want to also adopt Ninject as my IoC container as it is lightweight, fast and will increase the exstensibility of my application going forward.
I have done a great deal of reading and I have managed to make a start on the arcitecture of this new application. However, I am not sure i have the right idea when using Ninject. The code...
Starting with Program.cs and related classes...
static class Program
{
[STAThread]
static void Main()
{
FileLogHandler fileLogHandler = new FileLogHandler(Utils.GetLogFilePath());
Log.LogHandler = fileLogHandler;
Log.Trace("Program.Main(): Logging initialized");
CompositionRoot.Initialize(new ApplicationModule());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(CompositionRoot.Resolve<ApplicationShellView>());
}
}
public class CompositionRoot
{
private static IKernel _ninjectKernel;
public static void Initialize(INinjectModule module)
{
_ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return _ninjectKernel.Get<T>();
}
}
public class ApplicationModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IApplicationShellView)).To(typeof(ApplicationShellView));
}
}
An my ApplicationShellView is
public partial class ApplicationShellView : Form, IApplicationShellView
{
public ApplicationShellView()
{
InitializeComponent();
}
public void InitializeView()
{
dockPanel.Theme = vS2012LightTheme;
}
}
with interface
public interface IApplicationShellView
{
void InitializeView();
}
The controller for this view is
public class ApplicationShellController
{
private IApplicationShellView view;
public ApplicationShellController(IApplicationShellView view)
{
view.InitializeView();
}
}
Currently the controller is redundant, and although this code works and my view displays, I have some important questions...
Should I be using the ApplicationShellController to initialize my form, currently this is not using MVC "pattern"?
It feels like I have written a Service Locator, and from what I have read, this is bad. How else should I be using Ninject for IoC to initialize my application?
Any other advice as to what I am doing right[if anything!]/wrong?
Thanks very much for your time.
No you should not be initializing your controller, this exactly what IoC and Ninject are for. When you initialize your view/form, Ninject should make the view fetch the controller it depends on, which will auto fetch controllers it depends on and so on.
Of course this won't work like you've set it up right now. For starters, your view needs to know the controller it depends on.
public partial class ApplicationShellView : Form, IApplicationShellView
{
private IApplicationShellController _controller;
public ApplicationShellView()
{
InitializeComponent();
init();
//InitializeView()
}
private void init() {
_controller = NinjectProgram.Kernel.Get<IApplicationShellController>();
//Because your view knows the controller you can always pass himself as parameter or even use setter to inject
//For example: _controller.SetView1(this);
}
public void InitializeView()
{
dockPanel.Theme = vS2012LightTheme;
}
}
public class ApplicationShellController : IApplicationShellController
{
//Implementes functionality for the MainForm.
public ApplicationShellController()
{
//Also possible to add other controllers with DI
}
}
This does indeed look like a Service Locator, simply initializing your view should do be sufficient.
public class NinjectProgram
{
//Gets the inject kernal for the program.
public static IKernel Kernel { get; protected set; }
}
public class Program : NinjectProgram
{
[STAThread]
private static void Main()
{
Kernel = new StandardKernel();
Kernel.Load(new ApplicationModule());
Application.Run(new ApplicationShellView());
}
}
public class ApplicationModule : NinjectModule
{
public override void Load()
{
//Here is where we define what implementations map to what interfaces.
Bind<IApplicationShellController>().To<ApplicationShellController>();
//We can also load other modules this project depends on.
Kernel.Load(new NinjectModule());
}
}
Don't try and make it too complicated, a good start is important but you can always apply changes when and where needed during development.
I believe the following GitHub project might be a good starting point: Example of how you might use Ninject within a WinForms application.
If you have any more questions, just leave a comment and I'll try to answer them as soon as possible
How can I get a single instance using Ninject? Here's my Service Module:
public class ServicesModule : NinjectModule
{
public override void Load()
{
Kernel.Bind<IDocumentServiceApi>().To<DocumentServiceApi>().InRequestScope();
Kernel.Bind<IConfigurationService>().To<ConfigurationService>().InRequestScope();
Kernel.Bind<IReportGenerationProcessor>().To<ReportGenerationProcessor>().InRequestScope();
}
}
I need an instance of IReportGenerationProcessor to fire off a message I am receiving from an Azure Service Bus Queue.
I've seen a lot of different ways, but none have worked for me. I constantly get the error :Object instance not set to an instance of an object.
//I do instantiate this class using new WebJobBase();
public class WebJobBase
{
public void ProcessMessage(BrokeredMessage message)
{
// Just need an instance of IReportGenerationProcessor here
var _processor = new ReportGenerationProcessor();
_processor.ProcessMessage(message);
}
}
Here's my IReportGenerationProcessor implementation:
public interface IReportGenerationProcessor
{
DocumentMetaData ProcessMessage(BrokeredMessage message);
}
public class ReportGenerationProcessor : IReportGenerationProcessor
{
// Go figure these don't work either
[Inject]
public IConfigurationService _config { get; set; }
[Inject]
public IDocumentServiceApi _docService { get; set; }
public DocumentMetaData ProcessMessage(BrokeredMessage message)
{
var report = message.GetBody<ReportMetaData>();
//Do some stuff
return new DocumentMetaData(); // just a place holder
}
}
If I can provide more information, please let me know. I'm not too knowledgeable on Ninject.
Okay, so the documentation kind of hinted at this, but they didn't use an Interface and registered .ToSelf().
Basically I needed to instantiate a new StandardKernel with my ServicesModule from above, and call the .Get<>(); method for my registered Interface.
IKernel kernel = new StandardKernel(new ServicesModule());
var processor = kernel.Get<IReportGenerationProcessor>();
processor.ProcessMessage(message);
If I have a class (class P) which makes use of some other re-usable component (class C) (eg a state manager), then if that component needs to access some data within my top level class (P), then what choices do I have?
The key thing is that I dont want to expose this data to the outside world, just to within components I know and trust and use within P.
public static class Program
{
private void Main()
{
var owner = new Owner();
// I can call Foo()!!!
((IOwner)owner).Foo();
}
}
public interface IOwner
{
void Foo();
}
public class Owner : IOwner
{
private Component m_component;
public void SomeExternalAPI()
{
m_component = new Component(this);
m_component.DoSomething();
}
void IOwner.Foo()
{
// do something
}
}
public class Component
{
private readonly IOwner m_owner;
public Component(IOwner owner)
{
m_owner = owner;
}
public void DoSomething()
{
m_owner.Foo();
}
}
I could use an interface on P, but this then exposes the data externally.
I could use an explicit interface on P, but this can be cast and so also easily exposes the data.
If I could somehow impart "Friendship" upon the component (which I created, and ideally at the instance level!), and make IOwner a friend-only interface then, it would be secure.
I know this is impossible in C# at the moment.
It comes up quite often for me.
Has anyone got any solutions or suggestions?
You can use the internal accessor on your interface and Component class.
internal interface IOwner
{
void Foo();
}
internal class Component
{
private readonly IOwner m_owner;
public Component(IOwner owner)
{
m_owner = owner;
}
public void DoSomething()
{
m_owner.Foo();
}
}
The Owner class would be public
public class Owner : IOwner
{
private Component m_component;
public void SomeExternalAPI()
{
m_component = new Component(this);
m_component.DoSomething();
}
void IOwner.Foo()
{
// do something
}
}
With this approach, you won't be able to access the interface nor the Component class from an external assembly
The client would only see the Owner class and its SomeExternalAPI() method.
var Owner = new Owner();
owner.SomeExternalAPI();
//owner.Foo() --> Won't compile!
//((IOwner)owner).Foo() --> Won't compile!
I think I've found a reasonable solution, altho its quite hard work and more code than I'd like
Use a proxy class, which implements the public IOwner interface, but which can then call into the actual owner using an internal IInternalOwner interface, which it was given on construction.
The proxy then acts like a token allowing the owner to be called by anyone it gives this token to. Its more code than I would like, and it would be nice if this was built into C# :-).
But, it works between assemblies (in fact I had 4 to test it!).
public class Owner : IInternalOwner
{
private ITheComponent m_component;
public void SomeExternalAPI()
{
var proxy = new Proxy(this);
m_component = ClassFactory.ConstructTheComponent(proxy);
m_component.DoSomething();
}
void IInternalOwner.Foo()
{
// do something
Console.WriteLine("Owner.Foo was called");
}
private class Proxy : IOwner
{
private IInternalOwner m_owner;
public Proxy(IInternalOwner owner)
{
m_owner = owner;
}
/// <summary>
/// pass through for each method & property!
/// </summary>
public void Foo()
{
m_owner.Foo();
}
}
}
internal interface IInternalOwner
{
void Foo();
}