How to StructureMap configuration? - c#

On AppEngine "Franch" and "English" as a dependency injection what do I do?
class Program
{
static void Main(string[] args)
{
IContainer container = ConfigureDependencies();
IAppEngine appEngine = container.GetInstance<IAppEngine>();
IGeeter g1 = container.GetInstance<IGeeter>("Franch");
IGeeter g2 = container.GetInstance<IGeeter>("English");
appEngine.Run();
}
private static IContainer ConfigureDependencies()
{
return new Container(x =>
{
x.For<IGeeter>().Add<FrenchGreeter>().Named("Franch");
x.For<IGeeter>().Add<EnglishGreeter>().Named("English");
x.For<IAppEngine>().Use<AppEngine>();
x.For<IGeeter>().Use<EnglishGreeter>();
x.For<IOutputDisplay>().Use<ConsoleOutputDisplay>();
});
}
}
public interface IAppEngine
{
void Run();
}
public interface IGeeter
{
string GetGreeting();
}
public interface IOutputDisplay
{
void Show(string message);
}
public class AppEngine : IAppEngine
{
private readonly IGeeter english;
private readonly IGeeter franch;
private readonly IOutputDisplay outputDisplay;
public AppEngine(IGeeter english,IGeeter franch, IOutputDisplay outputDisplay)
{
this.english = english;
this.franch = franch;
this.outputDisplay = outputDisplay;
}
public void Run()
{
outputDisplay.Show(greeter.GetGreeting());
}
}
public class EnglishGreeter : IGeeter
{
public string GetGreeting()
{
return "Hello";
}
}
public class FrenchGreeter : IGeeter
{
public string GetGreeting()
{
return "Bonjour";
}
}

As the contract for FrenchGreeter and EnglishGreeter is the same, StructureMap will not know which to use. For each wireing it uses only one instance per contract. Try something like this:
For<IGreeter>().Use<FrenchGreeter>().Named("French");
For<IGreeter>().Use<EnglishGreeter>().Named("English");
For<IAppEngine>().Use<AppEngine>()
.Ctor<IGreeter>("French").Is(x => x.TheInstanceNamed("French"))
.Ctor<IGreeter>("English").Is(x => x.TheInstanceNamed("English"));

Related

How to fix a circular reference in .NET Core DI

Running into a circular reference from DI into my business services. Not sure what the best way to go about this is. I unfortunately can't remove from either service as I need them in both.
Below is an example of of my problem (not my actual services).
CarService
public class CarService
{
private readonly CarRepository _carRepository;
private readonly RecallService _recallService;
public CarService(CarRepository carRepository, RecallService recallService)
{
_carRepository = carRepository;
_recallService = recallService
}
public void RemoveRecallForCar(Recall recall)
{
//code
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_recallService.SendRecall(carGuid);
}
}
}
}
RecallService
public class RecallService
{
private readonly RecallRepository _recallRepository;
private readonly CarService _carService;
public RecallService(RecallRepository recallRepository,CarService carService)
{
_recallRepository = recallRepository;
_carService = carService
}
public void SendRecall(Guid carGuid)
{
// recall code
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
}
}
I expect to be able to inject services into services without circular references
You can change your code like below, it will help you fix the circular references issue.
ICustomService.cs
public interface ICustomService
{
void SendRecall(Guid carGuid);
void RemoveRecallForCar(Recall recall);
}
RecallService.cs
public class RecallService : ICustomService
{
private readonly RecallRepository _recallRepository;
private readonly CarService _carService;
public RecallService(RecallRepository recallRepository, CarService carService)
{
_recallRepository = recallRepository;
_carService = carService;
}
public void SendRecall(Guid carGuid)
{
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
public void RemoveRecallForCar(Recall recall)
{
}
}
CarService.cs
public class CarService
{
private readonly CarRepository _carRepository;
private readonly ICustomService _customService;
public CarService(CarRepository carRepository, ICustomService customService)
{
_carRepository = carRepository;
_customService = customService;
}
public void RemoveRecallForCar(Recall recall)
{
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_customService .SendRecall(carGuid);
}
}
}
Own way is, use Autofac or another DI library.
The other way ,that not a good solution, is you can divided your services to multiple services.
CarService1 :
public class CarService1
{
private readonly CarRepository _carRepository;
public CarrContactService(CarRepository carRepository)
{
_carRepository = carRepository;
}
public void RemoveRecallForCar(Recall recall)
{
//code
}
}
CarService2:
public class CarService2
{
private readonly CarRepository _carRepository;
private readonly RecallService _recallService;
public CarrContactService(CarRepository carRepository, RecallService recallService)
{
_carRepository = carRepository;
_recallService = recallService
}
public void SendRecall(Guid carGuid)
{
Car car = _carRepository.Get(carGuid);
if (car.Model == "Ford")
{
_recallService.SendRecall(carGuid);
}
}
}
RecallService :
public class RecallService
{
private readonly RecallRepository _recallRepository;
private readonly CarService1 _carService;
public RecallService(RecallRepository recallRepository,CarService1 carService)
{
_recallRepository = recallRepository;
_carService = carService
}
public void SendRecall(Guid carGuid)
{
// recall code
}
public GetRecalls()
{
List<Recall> recalls = _recallRepository.Fetch(x => x.IsActive).ToList();
foreach(var recall in recalls)
{
_carService.RemoveRecallForCar(recall);
}
}
}

how to resolve a type safe collection in the constructor?

I have this object structure
public interface IHandler<in TMessage>
{
void HandleMessage(TMessage messageType);
}
public class MessageType1
{
}
public class MessageType2
{
}
public class HandlerMessageType1 : IHandler<MessageType1>
{
public void HandleMessage(T messageType)
{
}
}
public class HandlerMessageType2 : IHandler<MessageType2>
{
public void HandleMessage(T messageType)
{
}
}
and the registration
container.Collection.Register(typeof(IHandler<>), new[]
{
typeof(HandlerMessageType1),
typeof(HandlerMessageType2)
});
how the constructor of the class where this is injected should look like?
public class ClientClass
{
public ClientClass(IEnumerable<IHandler<>> handlers)
{
}
}
like this doesn't work... how the signature of the client class constructor should look like?
this was edited to improve the example.
tkx in advance
Paulo Aboim Pinto
I Know if I understood, but with unity you can have:
public class Handler1 : IHandler
{
public void HandlerType()
{
Console.WriteLine("Handler1");
}
}
public class Handler2 : IHandler
{
public void HandlerType()
{
Console.WriteLine("Handler2");
}
}
public interface IHandler
{
void HandlerType();
}
Unity configuration
public static class DependencyConfiguration
{
public static UnityContainer Config()
{
var unity = new UnityContainer();
unity.RegisterType<IHandler, Handler1>("Handler1");
unity.RegisterType<IHandler, Handler2>("Handler2");
unity.RegisterType<IEnumerable<IHandler>>();
return unity;
}
}
A class to resolve:
public class ListOfTypes
{
private List<IHandler> handlers;
public ListOfTypes(IEnumerable<IHandler> handlers)
{
this.handlers = handlers.ToList();
}
public void PrintHandlers()
{
handlers.ForEach(_ => _.HandlerType());
}
}
The program:
static void Main(string[] args)
{
Console.WriteLine("Resolve sample");
var unity = DependencyConfiguration.Config();
var lstOfTypes = unity.Resolve<ListOfTypes>();
lstOfTypes.PrintHandlers();
Console.ReadLine();
}
Result:

tdd ioc container ninject contextual binding

I need some help with using contextual binding with ninject
I Have something like this :
public interface ISound
{
String Sound();
}
public class Cat : Animal
{
private string category;
private ISound sound;
public Cat(ISound sound, int age, string name, string sex, string category)
: base(age, name, sex)
{
this.sound = sound;
this.category = category;
}
public class CatSound : ISound
{
public String Sound()
{
return "Meow";
}
}
and exactly the same Dog Sound who implemets Sound
and my bindingmodule:
public class BindingModule:NinjectModule
{
private readonly SelectorMode _typeofsound;
public new StandardKernel Kernel => ServiceLocator.Kernel;
public BindingModule(SelectorMode mode)
{
_typeofsound = mode;
}
public override void Load()
{
if (_typeofsound == SelectorMode.Dog)
{
Kernel.Bind<ISound>().To<DogSound>();
}
else if(_typeofsound==SelectorMode.Cat)
{
Kernel.Bind<ISound>().To<CatSound>();
}
else
{
Kernel.Bind<ISound>().To<HorseSound>();
}
}
public class SelectorMode
{
public static SelectorMode Cat;
public static SelectorMode Horse;
public static SelectorMode Dog;
}
}
and the test i'm trying to run
public class WhenBindingCat:GivenABindingModule
{
[TestMethod]
public void SouldBindItToCat()
{
// var kernel=new Ninject.StandardKernel(new )
var sut = new BindingModule(SelectorMode.Cat);
sut.Load();
}
and it don't know how i should assert here
Try something like this:
[TestMethod]
public void SouldBindItToCat()
{
var sut = new BindingModule(SelectorMode.Cat);
IKernel kernel = new StandardKernel(sut);
Assert.IsTrue(kernel.Get<ISound>() is Cat);
}
and
replace SelectorMode class by enum
public enum SelectorMode
{
Cat, Horse, Dog
}

Implement abstract method of instance on initialization

There is a way to implement an abstract method of instance on initialization in C# like in Java?
public static abstract class A
{
public abstract String GetMsg();
public void Print()
{
System.out.println(GetMsg());
}
}
public static void main(String[] args)
{
A a = new A()
{
#Override
public String GetMsg()
{
return "Hello";
}
};
a.Print();
}
No you can't - but you can achieve the same end by using a Func<string>:
using System;
namespace Demo
{
public sealed class A
{
public Func<string> GetMsg { get; }
public A(Func<string> getMsg)
{
GetMsg = getMsg;
}
public void Print()
{
Console.WriteLine(GetMsg());
}
}
public static class Program
{
public static void Main()
{
var a = new A(() => "Hello");
a.Print();
}
}
}
Alternatively, if you want to be able to change the GetMsg property after initialization:
using System;
namespace Demo
{
public sealed class A
{
public Func<string> GetMsg { get; set; } = () => "Default";
public void Print()
{
Console.WriteLine(GetMsg());
}
}
public static class Program
{
public static void Main()
{
var a = new A(){ GetMsg = () => "Hello" };
a.Print();
}
}
}
(This uses c#6 syntax - you'd have to modify it slightly for earlier versions.)

How to code a good Offline-Online Dispatcher

Let's assume that I have this scenario: I have got 2 repositories of information, and I want to access both, but it would be nice to leave the task of deciding which repo to use to common class.
The goal is to accomplish this with something similar to the code I've wrote below, but this sounds pretty bad:
where TOnline : class
where TOffline : class
where TContract : class
Sure I can ommit that, but bassically what I'm asking is what to do in order to stop using reflection and go typed. Maybe any design-pattern recomendation?
Code (if you copy/paste this on a console app replacing the Program class you should be able to run the example)
using CustomerDispatcher = DispatcherProxy<CustomerOnline, CustomerOffline, ICustomer>;
public interface ICustomer
{
string Get(int id);
}
public class CustomerOnline : ICustomer
{
public string Get(int id)
{
// Get From intranet DB
return "From DB";
}
}
public class CustomerOffline : ICustomer
{
public string Get(int id)
{
// Get From local storage
return "From local storage";
}
}
public class DispatcherProxy<TOnline, TOffline, TContract>
where TOnline : class
where TOffline : class
where TContract : class
{
public TContract Instance { get; set; }
public bool IsConnected { get; set; }
public DispatcherProxy()
{
// Asume that I check if it's connected or not
if (this.IsConnected)
this.Instance = (TContract)Activator.CreateInstance(typeof(TOnline));
else
this.Instance = (TContract)Activator.CreateInstance(typeof(TOffline));
}
}
class Program
{
static void Main(string[] args)
{
var customerDispatcher = new CustomerDispatcher();
Console.WriteLine("Result: " + customerDispatcher.Instance.Get(1));
Console.Read();
}
}
Thanks in advance!
You can add the new() constraint:
public class DispatcherProxy<TOnline, TOffline, TContract>
where TOnline : class, new()
where TOffline : class, new()
where TContract : class //isn't TContract an interface?
{
public TContract Instance { get; set; }
public bool IsConnected { get; set; }
public DispatcherProxy()
{
// Asume that I check if it's connected or not
if (this.IsConnected)
this.Instance = new TOnline() as TContract;
else
this.Instance = new TOffline() as TContract;
}
}
In case any of you are interested, I had to change the way I did this because it was checking connection at Constructor Level, and I needed that check at Operation Level.
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
namespace ConsoleApplication1
{
public enum ConnectionStatus
{
Online,
Offline,
System // System checks connectivity
}
public static class Connectivity
{
private static ConnectionStatus ConnectionStatus = ConnectionStatus.Offline;
public static void ForceConnectionStatus(ConnectionStatus connectionStatus)
{
ConnectionStatus = connectionStatus;
}
public static bool IsConnected()
{
switch (ConnectionStatus)
{
case ConnectionStatus.Online:
return true;
case ConnectionStatus.Offline:
return false;
case ConnectionStatus.System:
return CheckConnection();
}
return false;
}
private static bool CheckConnection()
{
return true;
}
}
public class Unity
{
public static IUnityContainer Container;
public static void Initialize()
{
Container = new UnityContainer();
Container.AddNewExtension<Interception>();
Container.RegisterType<ILogger, OnlineLogger>();
Container.Configure<Interception>().SetInterceptorFor<ILogger>(new InterfaceInterceptor());
}
}
class Program
{
static void Main(string[] args)
{
Unity.Initialize();
var r = new Router<ILogger, OnlineLogger, OnlineLogger>();
Connectivity.ForceConnectionStatus(ConnectionStatus.Offline);
Console.WriteLine("Calling Online, will attend offline: ");
r.Logger.Write("Used offline.");
Connectivity.ForceConnectionStatus(ConnectionStatus.Online);
Console.WriteLine("Calling Online, will attend online: ");
r.Logger.Write("Used Online. Clap Clap Clap.");
Console.ReadKey();
}
}
public class Router<TContract, TOnline, TOffline>
where TOnline : TContract
where TOffline : TContract
{
public TContract Logger;
public Router()
{
Logger = Unity.Container.Resolve<TContract>();
}
}
public interface IOnline
{
IOffline Offline { get; set; }
}
public interface IOffline
{
}
public interface ILogger
{
[Test()]
void Write(string message);
}
public class OnlineLogger : ILogger, IOnline
{
public IOffline Offline { get; set; }
public OnlineLogger()
{
this.Offline = new OfflineLogger();
}
public void Write(string message)
{
Console.WriteLine("Online Logger: " + message);
}
}
public class OfflineLogger : ILogger, IOffline
{
public IOnline Online { get; set; }
public void Write(string message)
{
Console.WriteLine("Offline Logger: " + message);
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public class TestAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new TestHandler();
}
}
public class TestHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("It's been intercepted.");
if (!Connectivity.IsConnected() && input.Target is IOnline)
{
Console.WriteLine("It's been canceled.");
var offline = ((input.Target as IOnline).Offline);
if (offline == null)
throw new Exception("Online class did not initialized Offline Dispatcher.");
var offlineResult = input.MethodBase.Invoke(offline, this.GetObjects(input.Inputs));
return input.CreateMethodReturn(offlineResult, this.GetObjects(input.Inputs));
}
return getNext()(input, getNext);
}
private object[] GetObjects(IParameterCollection parameterCollection)
{
var parameters = new object[parameterCollection.Count];
int i = 0;
foreach (var parameter in parameterCollection)
{
parameters[i] = parameter;
i++;
}
return parameters;
}
}
}

Categories

Resources