i am trying to inject through property in the following service, if I try constructor injection it works but I want to do property injection, what am I missing?
public class SodaService
{
public ISoda _s;
//public SodaService(ISoda s)
//{
// _s = s;
//}
public string GetSoda()
{
return _s.SodaName;
}
}
//Soda Class implementing ISoda
public class Soda : ISoda
{
public string SodaName
{
get { return "Default Soda"; }
}
}
public interface ISoda
{
string SodaName { get; }
}
//Main calling program
class Program
{
static void Main(string[] args)
{
var container = GetContainer();
SodaService s=container.Resolve<SodaService>();
Console.Write(s.GetSoda());
Console.Read();
}
private static IContainer GetContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>()
.PropertiesAutowired();
var container = builder.Build();
return container;
}
}
EDIT:
The above was solved and i have one more question....
How can i make something like this work, i do not want to use
s = container.Resolve< ISodaService >();
and instead the dependencies should be automatically injected when i run the program
class Program
{
public static ISodaService s { get; set; }
static void Main(string[] args)
{
SetUpContainer();
//s = container.Resolve<ISodaService>();
Console.Write(s.GetSoda());
Console.Read();
}
private static void SetUpContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>().As<ISodaService>().PropertiesAutowired();
builder.Build();
}
}
The problem you have is Main method is static. Instanciate a class of Program and use is as non static class
class Program
{
public ISodaService s { get; set; }
static void Main(string[] args)
{
var resolver=SetUpContainer();
var instance=resolver.Resolve<Program>();
instance.Execute(args);
}
public void Execute(string[] args)
{
Console.Write(s.GetSoda());
Console.Read();
}
private Autofac.IContainer void SetUpContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<Soda>().As<ISoda>();
builder.RegisterType<SodaService>().As<ISodaService>().PropertiesAutowired();
builder.RegisterType<Program>().PropertiesAutowired();
return builder.Build();
}
}
Related
I can do this with StructureMap using Constructor Injection. However I cannot find a way to do this with Simple Injector. Here is some code that illustrates this (sorry for the length)
I've looked at the lambda in the Register method, but can't seem to understand how to call a single application wide instance of the container to get the one instance I need.
These are the object graphs I wish to construct:
var bannerTalker =
new LoudMouth(
new ConsoleShouter(), // Implements IConsoleVoicer
new ObnoxiousBannerGenerator());
var plainTalker =
new TimidSpeaker(
new ConsoleWhisperer()); // Implements IConsoleVoicer
Here's the code:
``` c#
public interface IConsoleVoicer
{
void SaySomething(string whatToSay);
}
public class ConsoleWhisperer : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToLower());
}
}
public class ConsoleShouter : IConsoleVoicer
{
public void SaySomething(string whatToSay)
{
Console.WriteLine(whatToSay?.ToUpper());
}
}
public interface IBannerGenerator
{
string GetBanner();
}
public class ObnoxiousBannerGenerator : IBannerGenerator
{
public string GetBanner()
{
return "OBNOXIOUS";
}
}
public interface IBannerTalker
{
void SayWithBanner(string somethingToSay);
}
public class LoudMouth : IBannerTalker
{
private IConsoleVoicer Voicer { get; set; }
private IBannerGenerator BannerGenerator { get; set; }
public LoudMouth(
IConsoleVoicer concoleVoicer, IBannerGenerator bannerGenerator)
{
Voicer = concoleVoicer;
BannerGenerator = bannerGenerator;
}
public void SayWithBanner(string somethingToSay)
{
Voicer.SaySomething(string.Format("{0}:{1}",
BannerGenerator.GetBanner(), somethingToSay));
}
}
public interface IPlainTalker
{
void SayIt(string somethingToSay);
}
public class TimidSpeaker : IPlainTalker
{
private IConsoleVoicer Voicer { get; set; }
public TimidSpeaker(IConsoleVoicer concoleVoicer)
{
Voicer = concoleVoicer;
}
public void SayIt(string somethingToSay)
{
Voicer.SaySomething(somethingToSay);
}
}
And this is what I've tried:
static void Main(string[] args)
{
var container = new Container();
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
//HERE IS THE DILEMMA! How do I assign
// to IBannerTalker a A LoudMouth contructed with a ConsoleShouter,
// and to IPlainTalkerTalker a A TimidSpeaker contructed with a ConsoleWhisperer
//container.Register<IConsoleVoicer, ConsoleShouter>();
container.Register<IConsoleVoicer, ConsoleWhisperer>();
var bannerTalker = container.GetInstance<IBannerTalker>();
var plainTalker = container.GetInstance<IPlainTalker>();
bannerTalker.SayWithBanner("i am a jerk");
plainTalker.SayIt("people like me");
}
Ric .Net is right in pointing you at the RegisterConditional methods. The following registrations complete your quest:
container.Register<IBannerGenerator, ObnoxiousBannerGenerator>();
container.Register<IPlainTalker, TimidSpeaker>();
container.Register<IBannerTalker, LoudMouth>();
container.RegisterConditional<IConsoleVoicer, ConsoleShouter>(
c => c.Consumer.ImplementationType == typeof(LoudMouth));
container.RegisterConditional<IConsoleVoicer, ConsoleWhisperer>(
c => c.Consumer.ImplementationType == typeof(TimidSpeaker));
I have an interface as below, which I use to add a specific language if it does not exist:
public interface IGetLanguagesService
{
void GetLanguages(ILocalizationService localization);
}
public class LanguageService : IGetLanguagesService
{
ILocalizationService _localizationService;
public void GetLanguages(ILocalizationService localization)
{
_localizationService = localization;
var currentLanguages = _localizationService.GetAllLanguages();
bool exists = false;
foreach (var currentLan in currentLanguages)
{
if (currentLan.IsoCode == "es-ES")
{
exists = true;
}
}
if (!exists)
{
AddLanguage(_localizationService);
}
}
public void AddLanguage(ILocalizationService localization)
{
var languageSE = new Language("es-ES") { CultureName = "es-ES", IsMandatory = true };
localization.Save(languageSE);
}
}
I want to use this at start-up so have created a component composer, which on Initialize() I want to call CallGetLanguages() but Im not entirely sure what should be in Initialize(), I think my DI may be wrong?
public class LanguagesComposer : ComponentComposer<LanguagesComponent>
{
public void Compose(Composition composition)
{
composition.Register<IGetLanguagesService>(Lifetime.Singleton);
composition.Register<ILocalizationService>(Lifetime.Singleton);
composition.Components().Append<LanguagesComponent>();
}
}
public class LanguagesComponent : IComponent
{
public void Initialize()
{
???????
}
public void Terminate()
{
throw new NotImplementedException();
}
IGetLanguagesService _getLanguagesService;
ILocalizationService _localization;
public void CallGetLanguages(IGetLanguagesService getLanguages, ILocalizationService localization)
{
_getLanguagesService = getLanguages;
_localization = localization;
_getLanguagesService.GetLanguages(localization);
}
}
You've passed ILocalizationService localization instance to LanguageService twice, pass it to constructor instead and use a constructor injection. The same issue with LanguagesComponent, pass all its dependencies to constructor instead of methods
Before using any dependency injection I'm using simple interface to make a loosely coupled code like below -
Program.cs
class Program
{
static void Main(string[] args)
{
Customer obj = new Customer(new OracleData());
obj.Add();
}
}
Customer.cs
public class Customer
{
private Idata iobj;
public Customer(Idata newiobj)
{
iobj = newiobj;
}
public void Add()
{
iobj.AddData();
}
}
OracleData.cs
public class OracleData : Idata
{
public void AddData()
{
throw new NotImplementedException();
}
}
SQLData.cs
public class SQLData : Idata
{
public void AddData()
{
throw new NotImplementedException();
}
}
Idata.cs
public interface Idata
{
void AddData();
}
Now I tried this using Autofac DI library -
I wonder it always its last injected class object , how to set resolve object using constructor or with any condition?
code using Autofac DI -
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Customer>();
builder.RegisterType<OracleData>().As<Idata>();
builder.RegisterType<SQLData>().As<Idata>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve<Idata>();
app.AddData();
}
//commented
//Customer obj = new Customer(new OracleData());
//obj.Add();
}
If you need to define which implementation you will use at the entry point you can do something like this:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Customer>();
if(args[0] == "oracle")
builder.RegisterType<OracleData>().As<Idata>();
else
builder.RegisterType<SQLData>().As<Idata>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve<Idata>();
app.AddData();
}
//commented
//Customer obj = new Customer(new OracleData());
//obj.Add();
}
In Unity, I can register a named type like this
using Microsoft.Practices.Unity;
var container = new UnityContainer();
container.RegisterType<IOutputService, ConsoleOutputService>("Console");
container.RegisterType<IOutputService, MessageBoxOutputService>("MessageBox");
container.RegisterType<ICalculatorReplLoop, CalculatorReplLoop>();
ICalculatorReplLoop loop = container.Resolve<ICalculatorReplLoop>();
and auto resolve it using attribute like this
public class CalculatorReplLoop : ICalculatorReplLoop
{
public CalculatorReplLoop() {}
[Dependency("MessageBox")]
public IOutputService OutputService { get; set; }
}
I know how to register Named Service in Autofac
using Autofac;
using Autofac.Core;
var builder = new ContainerBuilder();
builder.RegisterType<ConsoleOutputService>().Named<IOutputService>("Console");
builder.RegisterType<MessageBoxOutputService>().Named<IOutputService>("MessageBox");
builder.RegisterType<CalculatorReplLoop>().As<ICalculatorReplLoop>().SingleInstance();
IContainer container = builder.Build();
ICalculatorReplLoop loop = container.Resolve<ICalculatorReplLoop>();
but how to resolve it inside CalculatorReplLoop class ?
Look at this Sample code and this is one of the ways of auto resolve the using autofac when you share a contract with two implementations.
using System;
using Autofac;
using Autofac.Features.Indexed;
namespace AutoFac
{
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>("online");
builder.RegisterType<OfflineState>().Keyed<IDeviceState>("offline");
builder.RegisterType<Modem>().AsImplementedInterfaces();
var container = builder.Build();
var r = container.Resolve<IModem>();
r.print();
}
}
public interface IDeviceState
{
string Get();
}
public class OnlineState : IDeviceState
{
public string Get()
{
return "OnlineState";
}
}
public class OfflineState : IDeviceState
{
public string Get()
{
return "OfflineState";
}
}
public class Modem : IModem
{
readonly IIndex<string, IDeviceState> _states;
private readonly IDeviceState _deviceState;
public Modem(IIndex<string, IDeviceState> states)
{
_states = states;
_deviceState = _states["online"];
//_deviceState = _states["offline"];
}
public void print()
{
Console.WriteLine(_deviceState.Get());
}
}
public interface IModem
{
void print();
}
}
My code is as follows
IUnityContainer container = new UnityContainer();
container
.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.ApplyAutoRegistration();
This is my first question.
I'm not sure whether I have used the LoadAssemblyFrom method correctly here:
ITest test = container.Resolve<ITest>();
When I try to compile I get the exception "ResolutionFailedException".
What am I doing wrong?
Thanks for your time in advance.
It appears that what you are looking for is this:
container.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.Include(If.ImplementsITypeName, Then.Register())
.ApplyAutoRegistration();
This will tell Unity.AutoRegistration to register all types where there is an interface with the same name, prefixed with I.
Here is a complete working console example showing how to set Unity up for registration by convention, then transfer control into the dependency injection world. You will have to add the Unity NuGet package for this to work.
Tested with Unity v3.5 and VS 2012.
#region
using System;
using Microsoft.Practices.Unity;
#endregion
namespace Demo___Unity
{
internal class Program
{
private static void Main(string[] args)
{
using (var container = new UnityContainer())
{
// Manual method.
//container.RegisterType<IEntryPoint, EntryPoint>();
//container.RegisterType<IInjected, Injected>();
// Set up registration by convention.
// http://blogs.msdn.com/b/agile/archive/2013/03/12/unity-configuration-registration-by-convention.aspx
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var controller = container.Resolve<IEntryPoint>();
controller.Main();
}
}
}
public interface IEntryPoint
{
string Name { get; set; }
void Main();
}
public class EntryPoint : IEntryPoint
{
private readonly IInjected Injected;
public EntryPoint(IInjected injected)
{
Injected = injected;
}
public void Main()
{
Console.Write("Hello, world!\n");
Injected.SubMain();
Injected2.SubMain();
Console.Write("[any key to continue]");
Console.ReadKey();
}
// Demonstrates property injection.
[Dependency]
public IInjected Injected2 { get; set; }
public string Name { get; set; }
}
public interface IInjected
{
void SubMain();
}
public class Injected : IInjected
{
public void SubMain()
{
Console.Write("Hello, sub world!\n");
}
public string Name { get; set; }
}
}