I am new to dryioc so excuse the ignorance:)
I would like to understand what the correct approach would be for the following,
Creating a console app that creates instance of dryioc container. Register a logger in the container (as singleton). Then instantiate a class from a class library (separate project) to be used in the console app and be able to reference the container (main app) from the class library to get an instance of logger. So the class library will utilise any logger registered in console app.
I'd prefer not to pass container as part of constructors in class library.
Thanks for any assistance.
Something like this. Probably true for any other container (or even without container):
namespace Core
{
public interface ILogger
{
void Log(string message);
}
}
namespace Lib
{
using Core;
public class Foo
{
readonly ILogger _logger;
public Foo(ILogger logger)
{
_logger = logger;
}
public void DoSomething()
{
_logger.Log("About to do something ...");
}
}
}
namespace ConsoleApp
{
using System;
using Core;
using Lib;
using DryIoc;
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
public class Program
{
public static void Main()
{
var c = new Container();
c.Register<ILogger, ConsoleLogger>(Reuse.Singleton);
c.Register<Foo>();
var foo = c.Resolve<Foo>();
foo.DoSomething();
}
}
}
Related
Is it possible in DryIoc container to figure out whether some singleton has been instantiated?
For instance
var container = new Container();
container.Register<IApplicationContext, ApplicationContext>( Reuse.Singleton );
// var context = container.Resolve<IApplicationContext>();
if ( container.IsInstantiated<IApplicationContext>() ) // Apparently this does not compile
{
// ...
}
// OR
if ( container.IsInstantiated<ApplicationContext>() )
{
// ...
}
There is no way at the moment and no such feature planned. You may create an issue to request this.
But I am wandering why it is needed. Cause singleton provides a guarantee to be created only once, so you may not worry or check for double creation.
Is it for something else?
Update
OK, in DryIoc you may register a "decorator" to control and provide information about decoratee creation, here is more on decorators:
[TestFixture]
public class SO_IsInstantiatedViaDecorator
{
[Test]
public void Test()
{
var c = new Container();
c.Register<IService, X>(Reuse.Singleton);
c.Register<XProvider>(Reuse.Singleton);
c.Register<IService>(
Made.Of(_ => ServiceInfo.Of<XProvider>(), p => p.Create(Arg.Of<Func<IService>>())),
Reuse.Singleton,
Setup.Decorator);
c.Register<A>();
var x = c.Resolve<XProvider>();
Assert.IsFalse(x.IsCreated);
c.Resolve<A>();
Assert.IsTrue(x.IsCreated);
}
public interface IService { }
public class X : IService { }
public class A
{
public A(IService service) { }
}
public class XProvider
{
public bool IsCreated { get; private set; }
public IService Create(Func<IService> factory)
{
IsCreated = true;
return factory();
}
}
}
This example also illustrates how powerful is composition of DryIoc decorators and factory methods.
How can I register an Open Generic type with another open generic and primitive injected in the constructor?See example below.In this example, Resolve is throwing "Unable to resolve String as parameter "connectionString"" exception. (you can check live code here)
using System;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.RegisterInstance("some_connection_string", serviceKey: "connectionString");
container.Register(typeof(Configuration<>), Reuse.Singleton);
container.Register(typeof (IEntityUpdater<>), typeof (SqlEntityUpdater<>), Reuse.Singleton);
var p = container.Resolve<IEntityUpdater<EventArgs>>();
Console.WriteLine(p);
}
}
public class Configuration<T> where T : class { }
internal interface IEntityUpdater<in T> where T : class
{
void Update(T entity);
}
internal class SqlEntityUpdater<T> : IEntityUpdater<T> where T : class
{
public SqlEntityUpdater(Configuration<T> configuration, string connectionString)
{
}
public void Update(T entity) { }
}
First, RegisterInstance is depricated, use UseInstance.
Second, the actual problem is that you registering instance with serviceKey and nowhere using this key for injection.
So, you either remove the serviceKey parameter.
Or, specify the key on injection side:
container.Register(typeof(IEntityUpdater<>), typeof(SqlEntityUpdater<>), Reuse.Singleton,
made: Parameters.Of.Type<string>(serviceKey: "connectionString"));
First of all, I beg your pardon if this question has been already answered, but I simply cannot be sure of my choice.
I am working on a C++ game engine and I want it to be according to the modern standards. I wrote it in OOP manner and I have a main class called ENGINE. Inside it, there are a couple of class instances that represent specific subsystems: WINDOW, D3D11_RENDERER, etc. I also have a logging system (LOGGER) which must be available to all subsystems.
Now, this global access to the logger poses me a problem. I am uncertain whether I should declare it as static, outside the ENGINE class and have a function that returns a reference to it or instance it inside ENGINEand make all subsystems point to it.
To give you a better idea of what I am talking about, I posted simplified versions of these scenarios (take into account that I removed a lot of meaningless functions).
First solution:
class LOGGER {...};
LOGGER* GetLogger()
{
static LOGGER Logger;
return &Logger;
}
// Just one example.
class WINDOW
{
void Function()
{
GetLogger()->Write();
}
};
class ENGINE
{
private:
WINDOW Window;
}
Note that Irrlicht engine does it like this:
class Printer
{
public:
static void Write();
static LOGGER* Logger;
};
And it can be globally accessed like this:
os::Printer::Write();
Second solution:
class LOGGER() {...};
// Same example.
class WINDOW
{
public:
void Initialize(LOGGER* pLogger)
{
Logger = pLogger;
}
void Function()
{
Logger->Write();
}
private:
LOGGER* Logger;
};
class ENGINE
{
public:
void Initialize()
{
Window.Initialize(&Logger);
}
private:
WINDOW Window;
LOGGER Logger;
}
I do not know which is the best solution and I would be glad if you could point me to the right one. Thank you in advance.
I think this diagram represents better what you need:
Your components should be log-agnostic, as their function don't depend on logging capabilities. This function should be delegated to the engine.
The engine itself can contain a Logger component, which handles the de facto logging.
So let's see some basic code:
class Engine {
private:
Logger& mLogger;
EngineComponent mComponents[10];
public:
Engine(Logger& logger):
mLogger(logger) {
}
void addComponent(EngineComponent& c, int pos) {
mComponents[pos] = c;
c.setEngine(this);
}
void log(const std::string& message) {
mLogger.write(message);
}
}
class EngineComponent {
private:
Engine* mEngine;
protected:
EngineComponent() {}
public:
void setEngine(Engine* engine) {
mEngine = engine;
}
void log(const std::string& message) {
if (mEngine != NULL) {
mEngine->log(message);
}
}
}
class Window : public EngineComponent {
// add implementation
}
class D3d11Renderer : public EngineComponent {
// add implementation
}
class Logger {
protected:
Logger() {}
}
class FileLogger : public Logger {
// add implementation
}
Hope it helps.
I am extending AbstractPhaseInterceptor, and I want to get hold of the JAXWS web service object, in INVOKE or PRE_INVOKE phase. How do I do this?
To be clear, I need to get a reference to the object that implements the web service methods, so:
#WebService(...)
public class ExampleWebService
{
#WebMethod(...)
public void doSomething(...)
{
}
}
public class MyInterceptor
extends AbstractPhaseInterceptor<Message>
{
public MyInterceptor()
{
super(Phase.INVOKE);
}
#Override
public void handleMessage(Message message)
throws Fault
{
ExampleWebService serviceObject = getServiceObject(message);
}
private static ExampleWebService getServiceObject(Message messsage)
{
// how do I implement this?
}
}
I do not test the code but something like that probably works.
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.frontend.ServerFactoryBean;
...
Server server = serverFactoryBean.create();
MyInterceptor myInterceptor = new MyInterceptor(server.getEndpoint());
server.getEndpoint().getInInterceptor().add(myInterceptor);
I am setting up some MSTest based unit tests. To make my life easier I want to use a base class that handles the generic setup and taredown all of my tests require. My base class looks like this:
[TestClass]
public class DBTestBase {
public TestContext TestContext { get; set; }
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext) {
var config = new XmlConfigurationSource("ARconfig_test.xml");
ActiveRecordStarter.Initialize(Assembly.Load("LocalModels"), config);
}
[TestInitialize()]
public void MyTestInitialize() {
ActiveRecordStarter.CreateSchema();
Before_each_test();
}
protected virtual void Before_each_test() { }
[TestCleanup()]
public void MyTestCleanup() {
After_each_test();
}
protected virtual void After_each_test() { }
}
My actual test class looks like this:
[TestClass]
public class question_tests : DBTestBase {
private void CreateInitialData() {
var question = new Question()
{
Name = "Test Question",
Description = "This is a simple test question"
};
question.Create();
}
protected override void Before_each_test() {
base.Before_each_test();
CreateInitialData();
}
[TestMethod]
public void test_fetching() {
var q = Question.FindAll();
Assert.AreEqual("Test Question", q[0].Name, "Incorrect name.");
}
}
The TestInitialize function works as expected. But the ClassInitialize function never runs. It does run if I add the following to my child class:
[ClassInitialize()]
public static void t(TestContext testContext) {
MyClassInitialize(testContext);
}
Is it possible to get my base class initialize function to run without referencing it in my child class?
ClassInitialize method is executed if and only if the concerned "class" contains at least one TestMethod, and at least one TestMethod from the class is selected for execution.
Confirm this was a problem for me too. I used a constructor on the base and a destructor for the cleanup
[TestClass]
public class question_tests : DBTestBase {
...
[TestCleanup()]
public void TestCleanup()
{
base.MyTestCleanup();
}