Open Generics with injected primitive - dryioc

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"));

Related

Boost::ex.DI - Inject parametrized object

In our c++ application, we create many objects, like this:
class Interface {
public:
static InterfaceImplementation Create(string s) {
return InterfaceImplementation(s);
}
};
class User {
public:
User() {
i = Interface::Create("User");
}
private:
Interface i;
};
Please note here, that the "User" class name and the string provided for the interface implementation match.
I would like to refactor this "pattern" and inject the interface by using e.g. Boost::ex.DI framework, but I haven't found, how to tell to the framework, to "inject instance with specific value"
class Interface {
};
class InterfaceImplementation : public Interface {
public:
InterfaceImplementation(string s) {
}
};
class User {
public:
User(<Interface implementation object created by string "User">) {
}
};
class Square {
public:
Square(<Interface implementation object created by string "Square">) {
}
};
Sorry, if I missed something from the documentation.

Resolution status in DryIoc container

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.

Avoid public `SetState()` interface in state pattern implementation in C++

The state pattern
itself is really nice pattern for implementing state machines because it allows to encapsulate state transitions logic in states themselves and adding a new state is actually becomes easier because you need to make changes only in relevant states.
But, it is usually avoided in description how should states be changed.
If you implement state change logic in Context then whole the point of pattern is missed, but if you implement state change logic in states, that means you need to set a new state in Context.
The most common way is to add the public method to Context SetState() and pass reference to Context to the state object, so it will be able to set a new state, but essentially it will allow the user to change state outside the state machine.
To avoid it I came to the following solutions:
class IContext {
public:
virtual void SetState(unique_ptr<IState> newState) = 0;
}
class Context : public IContext {
private:
virtual void SetState(unique_ptr<IState> newState) override { ... };
}
But in general changing the method scope in derived class doesn't look really good.
Is there another way to hide this interface (friend class is not an option because it requires to change the Context class for each state being added)?
You could consider having the handler handle()returning the next state...
class IState {
public:
virtual unique_ptr<IState> handle(Context&) = 0;
};
class StateA : public IState {
private:
// presented inline for simplicity, but should be in .cpp
// because of circular dependency.
//
virtual unique_ptr<IState> handle(Context& ctx) override
{
//...
if (/*...*/)
return make_unique(StateB{});
//... including other state switch..
return { nullptr }; // returning null indicates no state change,
// returning unique_ptr<>(this) is not really an option.
}
};
The goal of the state pattern is to hide/encapsulate different implementations from the caller.However, caller only needs to know what type of implementation it needs.
Not sure how much this helps, but I just implemented a sample state machine in C# that uses the observer pattern and a tiny bit of reflection to get a very clean and encapsulated implementation of the state pattern.
Context.cs:
using System;
using System.Collections.Generic;
using System.Linq;
public class Context
{
State State { get; set; }
List<State> States { get; }
public Context()
{
States = new()
{
new HappyState(),
new SadState(),
};
SetState<HappyState>();
}
void DoSomething() => State?.DoSomething();
string ReturnSomething() => State?.ReturnSomething();
void SetState<StateType>() where StateType : State => SetState(typeof(StateType));
void SetState(Type stateType)
{
if (!stateType.IsSubclassOf(typeof(State))) return;
var nextState = States.Where(e => e.GetType() == stateType).First();
if (nextState is null) return;
if (State is not null)
{
State?.ExitState();
State.ChangeRequested -= OnChangeRequested;
}
State = nextState;
State.ChangeRequested += OnChangeRequested;
State.EnterState();
}
void OnChangeRequested(Type stateType) => SetState(stateType);
}
State.cs:
using System;
public abstract class State
{
public event Action<Type> ChangeRequested;
protected void SetState<StateType>() where StateType : State
{
ChangeRequested?.Invoke(typeof(StateType));
}
public virtual void EnterState() { }
public virtual void ExitState() { }
public virtual void DoSomething() { }
public virtual string ReturnSomething() => "";
}
You can then use this Syntax in either the Context or any State
SetState<HappyState>();
Link to Repository

How to use dryioc container from main app in class library

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();
}
}
}

Unit Testing - Use of Structuremap with MOQ

I want generic/oneline statements for structuremap configuration . please see the following code and suggest the changes :
Structuremap configuration class :
class StructureMapTestConfigurationRegistry : Registry
{
/// <summary>
/// Initializes a new instance of the <see cref="DependencyConfigurationRegistry"/> class.
/// </summary>
public StructureMapTestConfigurationRegistry()
{
For<Repository.IRepository<Report>>().Use(MockObjectGenerator<Report>.RepositoryMockSetup());
For<Repository.IRepository<RelatedContent>>().Use(MockObjectGenerator<RelatedContent>.RepositoryMockSetup());
For<Repository.IRepository<Tags>>().Use(MockObjectGenerator<Tags>.RepositoryMockSetup());
For<Repository.IRepository<ArticleTag>>().Use(MockObjectGenerator<ArticleTag>.RepositoryMockSetup());
For<Repository.IRepository<ReferenceBookTag>>().Use(MockObjectGenerator<ReferenceBookTag>.RepositoryMockSetup());
For<Repository.IRepository<EventsTag>>().Use(MockObjectGenerator<EventsTag>.RepositoryMockSetup());
For<Repository.IRepository<CountryFactfileTag>>().Use(MockObjectGenerator<CountryFactfileTag>.RepositoryMockSetup());
}
BootStrapper Class :
public static class TestBootstrapper
{
public static void TestConfigureStructureMap()
{
ObjectFactory.Container.Dispose();
ObjectFactory.Initialize(o => o.AddRegistry(new StructureMapTestConfigurationRegistry()));
ObjectFactory.Container.AssertConfigurationIsValid();
}
}
MockObjectGenerator Class :
public static class MockObjectGenerator<TEntity> where TEntity : class
{
private static List<TEntity> DummyTable
{
get
{
return MockEntities.GetData<TEntity>();
}
}
public static IRepository<TEntity> RepositoryMockSetup()
{
Mock<IRepository<TEntity>> repository = new Mock<IRepository<TEntity>>(MockBehavior.Strict);
repository.Setup(o => o.Fetch(It.IsAny<Expression<Func<TEntity, bool>>>())).Returns((Expression<Func<TEntity, bool>> i) => DummyTable.Where(i.Compile()).ToList());
repository.Setup(o => o.Create(It.IsAny<IEnumerable<TEntity>>())).Callback<IEnumerable<TEntity>>(items => DummyTable.AddRange(items));
repository.Setup(o => o.Delete(It.IsAny<TEntity>())).Callback<TEntity>(item => DummyTable.Remove(item));
}
}
**Mock Entities Class :**
public static class MockEntities
{
public static Dictionary<string, dynamic> MockData = new Dictionary<string, dynamic>();
public static void LoadData()
{
MockData.Add(typeof(CMSModel.Article).Name, ArticleTestData.GetTestRecords());
MockData.Add(typeof(CMSModel.ArticleTag).Name, RelatedArticleContentTestData.GetTestRecords());
}
public static List<T> GetData<T>() where T : class
{
return (List<T>)MockData[typeof(T).Name];
}
}
Note :
This has been done so that in actual unit test , We dont have to write setup methods since that is done while creating dependent object using structuremap.
It works fine, but I want to refactor the configuration file code to generic
I have writen it for implentation like this :
For(typeof(Repository.IRepository<>)).Use(typeof(Repository.Repository<>));
is it possible for unit test configuration ?
It is possible, though you'd need to specify all types entity types that are going to be used and pass them as Types. And you'll need to use non-generic version of functions (to be able to write For(type) instead of For). That way all your functions would work only on type variables and would look like simple methods.