NancyFx and TinyIoc - c#

I am new to dependency injection.I am having problems understanding how to use the nancyFx bootstrapper and TinyIoc. I want to reference a dependency but can not understatnd how to do it. I can not seem to find the correct info anywhere or I am just misunderstanding it.This is my code:
public class Startup1
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
My interface:
public interface IPerson
{
string Getname();
}
My implementation:
public class Person : IPerson
{
public string Name { get; set; }
public string Getname()
{
return Name;
}
}
My program
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Bill";
string uri = "http://localhost:8080/";
using (WebApp.Start<Startup1>(uri))
{
Console.WriteLine("Started");
Console.ReadKey();
Console.WriteLine("Stopping");
}
}
My nancy bootstrapper:
public class MyNancyBoot : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
//base.ConfigureApplicationContainer(container);
container.Register<IPerson>(new Person());
}
}
My nancyModule:
public class MyNancyModule : NancyModule
{
public MyNancyModule(IPerson person)
{
Get["/"] = _ =>
{
var x = TinyIoCContainer.Current.Resolve<IPerson>();
return "OK";
};
}
}
This return an error in MyNancyModule.
var x = TinyIoCContainer.Current.Resolve<IPerson>();
Ok so how do I get my person into MyNancyModule?

I want to reference a dependency but can not understatnd how to do it.
I think there are a couple of things to look at here.
You are mistakenly thinking that you need to somehow pass in, on the controller constructor, any type you may want to return from your Get["/"] controller operation. This is not the case. If one of the service operations happens to return a Person type, you do not need to inject that person type into the constructor. Rather you could just do something like:
Get["/"] = _ =>
{
var x = new List<Person>();
return Response.AsJson(x);
};
Obviously this service operation is of very limited use, as it will always return an empty list of type Person.
So what you need is a dependency which gets Persons. Eg:
interface IGetPersons
{
List<Person> GetAll();
}
In order for this to be used inside the controller, Tiny Ioc will need to know about it. So that is where you can then register this type with Tiny Ioc.
container.Register<IGetPersons>();
This brings us onto the second thing you are struggling with, which is how Tiny Ioc works.
After you add the implicit registration in the nancy bootstrapper, Tiny Ioc will then scan your assemblies and find the implementation of IGetPersons automatically! (This is assuming there is a single implementation. If more than one you will actually need to do more work but that's another story).
This magic then allows you to just modify your controller thus:
public MyNancyModule(IGetPersons personGetter)
{
Get["/"] = _ =>
{
var x = List<Person> personGetter.GetAll(); // Look, don't need to resolve this manually!
return Response.AsJson(x);
};
}
Tiny Ioc will take care of resolving the injected type to the IGetPersons implementation, which you are then free to use through the controller.
Lets say a client makes an http post to a win form app which is
running a nancy service. How do get the data from the nancy service to
the win form.
Have a look at the following: http://weblogs.asp.net/rweigelt/10235654
The author is using the Managed Extensibility Framework (MEF) to make changes to what I assume is some kind of singleton provided by the framework:
container.Register(MefContainer.GetExportedValue<IRemoteAccess>());

Related

Is Service Locator an anti pattern in a pluggable architecture?

I know this question might look like it's a duplicate but please let me explain.
So I created several components that use a pluggable architecture, basically I can freely add new implementations and they will be injected and processed automatically for me. This is really handy in several scenarios.
I'm going to talk about the simplest one, validating components.
One of the reasons to use a design like this is that I like to expose my roles explicitly as explained by Udi Dahan
Basically I have code like this:
public interface IValidatorRuner
{
void Run<TTarget>(TTarget target);
}
public class ValidatorRunenr : IValidatorRuner
{
private readonly IServiceLocator _serviceLocator;
public ValidatorRunenr(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}
public void Run<TTarget>(TTarget target)
{
// this is the dynamic/pluggable phase
// is this an antipattern???
var foundValdiators = _serviceLocator.GetAllInstances<IValidator<TTarget>>();
foreach (var valdiator in foundValdiators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
This code lets me expose my validation rules explicitly like this:
//this will allow me to create validators in this way
//and they will be automatically injected and resolved for me
//(easy, to read, easy to write, easy to test, pff I could even smoke this validator easily)
public class OneValdiationRuleExplicitlyExposedAndEasyToTest : IValidator<Person>
{
public bool IsSatisfiedBy(Person target)
{
return target.Age > 18;
}
}
public class Person
{
public int Age { get; set; }
}
public interface IValidator<TTarget>
{
bool IsSatisfiedBy(TTarget target);
}
And I will use this code like this:
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner _validatorRuner;
public SomeCommandHandler(IValidatorRuner validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
Validation was just one example, I also use it to fire domain events and to run pipelines and filters in the same pluggable way
Is using the service locator in this way an anti-pattern?
I know I might be hiding some dependencies, but the thing is that the dependencies are dynamically injected and discovered when the application initializes (Composition root)
Your thoughts will be greatly appreciated
In my opinion, the primary issue with your code sample is that the service locator is itself injected into the implementation of ValidatorRunner. For me, this is an anti-pattern, but perhaps not the one you're asking about.
Any answer I might give boils down to the capabilities of your service locator implementation. But for sure it should not be passed into the constructor of your class. Instead, the service locator should itself pass these things in when you ask it for an implementation of "IValidatorRuner"
As an example, you can inject a factory that knows how to load the dynamic validator instances for a given type.
If anyone is interested, I found a way to remove the ServiceLocator in my objects and still dynamically load/discover dependencies at run time.
The way I solved it was by registering my components in my DI container in the following way (using the Mediator pattern):
Binding mediator (shortbus) with/to ninject
var kernel = new StandardKernel();
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFromAny(
new[]
{
typeof(IValidatorRunner<>)
})
.BindDefaultInterfaces());
And my final implementation looks like:
public interface IValidatorRuner<in TTarget>
{
void Run(TTarget target);
}
public class ValidatorRunenr<TTarget> : IValidatorRuner<TTarget>
{
private readonly IEnumerable<IValidator<TTarget>> _validators;
public ValidatorRunenr(IEnumerable<IValidator<TTarget>> validators)
{
_validators = validators;
}
public void Run(TTarget target)
{
foreach (var valdiator in _validators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
Usage
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> _validatorRuner;
public SomeCommandHandler(IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
In few words, by registering an opened generic type, my container resolves any call to that type creating a concrete-closed-generic-type instance at runtime for me.
As you can see in the usage, I do not have to create a specific concrete-closed-generic type of IValidatorRunner<OneValdiationRuleExplicitlyExposedAndEasyToTest> because the container creates one for me.
And there you go, now I'm happy because I removed the service locator from my domain objects =)

Setting variable from ServiceHost

In my project, I have a service class.
class KLAService : IKLAService
{
CentralLogic centralLogic;
.....
}
Using this class, I set up the ServiceHost like this:
centralLogic = new CentralLogic();
ServiceHost host = new ServiceHost(typeof(KLAService));
using (host)
{
host.Open();
Application app = new Application();
app.Run(new ConfigurationWPF.MainWindow(centralLogic));
host.Close();
}
As it might have become clear, I create one instance of the CentralLogic class. This very instance is used in the UI but also in the host to manage other stuff in my solution.
The problem I'm having now, is to set the centralLogic-variable in the KLAService-class (or in the host). I don't know how to do this. I've read about the plugin Ninject and how to inject objects in the service, but that's way out of my league and I can't help but think there is an easy way.
How can I achieve my goal the best?
EDIT: Another solution proposed was to start the ServiceHost and let CentralLogic get created there instead of the other way around. That would mean the ServiceHost needs some sort of a constructor. I don't know what the best practice is nor how to achieve this. Any help is appreciated.
I don't think you really need dependency injection. Since CentralLogic has a single instance, it is effectively a singleton. Read about singleton pattern here.
You can implement the singleton pattern on CentralLogic
public sealed class CentralLogic
{
private static readonly Lazy<CentralLogic> lazy =
new Lazy<CentralLogic>(() => new CentralLogic());
public static CentralLogic Instance { get { return lazy.Value; } }
private CentralLogic()
{
}
}
Then in the Service Impl's contructor (and in the UI), you get the instance, this way:
class KLAService : IKLAService
{
CentralLogic m_centralLogic;
public KLAService()
{
m_centralLogic = CentralLogic.Instance;
....
}
}
There is no need to pass anything to ServiceHost.
The most important thing for you here is make sure your CentralLogic's instance is thread safe.
The simplest solution is to create a singleton for the CentralLogic class.
If you want to do dependency injection, I would recommend structuremap and you can set it up pretty easily with nuget and I'd advice for you to do the injection in the KLAService
Here's a console app that shows how to set it up and inject some local object to other classes:
class KLAService : IKLAService
{
// Constructor injection
public KLAService(ICentralLogic logic)
{
Console.WriteLine(logic.Value);
}
// Manual instance creation
internal void PrintLogicValue()
{
var logic = ObjectFactory.Container.GetInstance<ICentralLogic>();
Console.WriteLine(logic.Value);
}
}
interface IKLAService
{
}
class CentralLogic : ICentralLogic
{
public int Value { get; set; }
public CentralLogic()
{
Value = 12345;
}
}
interface ICentralLogic
{
int Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
var logic = new CentralLogic();
ObjectFactory.Initialize(x => x.Scan(scan => scan.TheCallingAssembly()));
ObjectFactory.Container.Configure(x => x.For<ICentralLogic>().Use(y => logic));
var service = ObjectFactory.Container.GetInstance<KLAService>();
service.PrintLogicValue();
Console.ReadKey();
}
}
When the code calls var service = ObjectFactory.Container.GetInstance<KLAService>(); the constructor expects an object of type ICentralLogic and the injector will provide the configured logic object.
Alternatively, you can manually get the configured object for ICentralLogic with ObjectFactory.Container.GetInstance<ICentralLogic>();.

TinyIoC - Multiple Implementations of Interface

I am just beginning to learn about IoC and Dependency Injection. I am planning on doing a MonoTouch project and wanted to use TinyIoC but I wanted to test it out first. I'm creating a dummy credit card processing console app and I'm having trouble with how to configure TinyIoC since I have multiple implementations of my interface. This is my test app.
Interface:
public interface IPaymentProcessor
{
void ProcessPayment(string cardNumber);
}
Two Implementations of the interface:
VisaPaymentProcessor
public class VisaPaymentProcessor : IPaymentProcessor
{
public void ProcessPayment(string cardNumber)
{
if (cardNumber.Length != 13 && cardNumber.Length != 16)
{
new ArgumentException("Card Number isn't the correct length");
}
// some code for processing payment
}
}
AmexPaymentProcessor
public class AmexPaymentProcessor : IPaymentProcessor
{
public void ProcessPayment(string cardNumber)
{
if (cardNumber.Length != 15)
{
new ArgumentException("Card Number isn't the correct length");
}
// some code for processing the payment
}
}
Simple stuff. Now I have a class that accepts the interface as a parameter in the constructor....
CreditCardProcessor
public class CreditCardProcessor
{
public IPaymentProcessor PaymentProcessor { get; set; }
public CreditCardProcessor(IPaymentProcessor processor)
{
this.PaymentProcessor = processor;
}
public void ProcessPayment(string creditCardNumber)
{
this.PaymentProcessor.ProcessPayment(creditCardNumber);
}
}
My console app looks like this....
class Program
{
static void Main(string[] args)
{
TinyIoCContainer.Current.AutoRegister();
var creditCardProcessor = TinyIoCContainer.Current.Resolve<CreditCardProcessor>();
creditCardProcessor.ProcessPayment("1234567890123456"); // 16 digits
}
}
So I am trying to figure out how to tell the Resolve which implementation of the interface to pass to the constructor. If I run this code, I will always use the VisaPaymentProcessor implementation.
So how can I make TinyIoC pass the AmexPaymentProcessor implementation to the constructor rather than the VisaPaymentProcessor(which seems to be the default)?
I haven't used TinyIoC myself, but I suspect you want:
TinyIoCContainer.Current.Register(typeof(IPaymentProcessor),
typeof(AmexPaymentProcessor));
(If you want to use Amex.)
There are various other Register overloads available, including one which takes a name to use, which may be useful when you resolve. It really depends on what you're trying to achieve, which isn't terribly clear from the question.
I'm not really sure what you're trying to achieve here, but if you have multiple implementations of an interface and you want a specific one then you need to register each one with a name, or use RegisterMultiple, which uses the type name for a name, then resolve using that name and use that along with NamedParameterOverloads to specify which one you want.
It sounds more like though that you might want some kind of ProcessorFactory, or a facade of some kind, that takes a dependency on IEnumerable and supplies/acts as a facade for the correct implementation depending on the number passed in.
Something like this in Global.asax or application entry (Modified for your example)
const string nameTrim = "paymentprocessor";
var type = typeof(IPaymentProcessor);
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(x => type.IsAssignableFrom(x) && x.IsClass).ToList()
.ForEach(t =>
{
var name = t.Name.ToLower();
if (name.EndsWith(nameTrim))
name = name.Substring(0, name.Length - nameTrim.Length);
TinyIoCContainer.Current.Register(type, t, name);
});
It finds alla implementations of IPaymentProcessor and registers them with classname
(-PaymentProcessor, if the classname ends with PaymentProcessor)
Then I can resolve for example "AmexPaymentProcessor" with
IPaymentProcessor handler;
if (TinyIoCContainer.Current.TryResolve("amex", out handler))
{
response = handler.ProcessPayment(cardNumber);
}

How to remove(unregister) registered instance from Unity mapping?

I meet one problem that i can't solve now.
I have the following:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
where UnityHelper.DefaultContainer is my helper for getting unity container with loaded configuration.
here I registered instance as an instance of IMyInterface.
So anywhere( some time after using) I want to remove this mapping. Remove it at all. How I can do it?
I have tried:
UnityHelper.DefaultContainer.Teardown(instance)
but is was unsuccessful and the following code returns instance anyway:
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
I had the same problem and just removed the registrations of the ContainerControlledLifetimeManager from my Container:
foreach (var registration in container.Registrations
.Where(p => p.RegisteredType == typeof(object)
&& p.Name == name
&& p.LifetimeManager.Type == typeof(ContainerControlledLifetimeManager)))
{
registration.LifetimeManager.RemoveValue();
}
This is an old question, but some answers are misleading, so I will provide my own.
You can´t do that with Unity. End of the story.
Calling RemoveValue on registrations lifetime managers does not achieve unregistration (more information about lifetime managers), and that method is not intended to unregister anything. So the final behaviour is unexpected and not convenient. Of course, RemoveValue makes even less sense if you register an implementation or a factory method, although the question is about unregistering instances.
Consider the next piece of code
public interface SomeInterface
{
int Foo { get; set; }
}
public class SomeImplementation: SomeInterface
{
public int Foo { get; set; }
}
static void Main(string[] args)
{
UnityContainer iocContainer = new UnityContainer();
string registerName = "instance";
//before any registration
Resolve<SomeInterface>(iocContainer, registerName);
iocContainer.RegisterInstance<SomeInterface>(registerName, new SomeImplementation());
//after registration
Resolve<SomeInterface>(iocContainer, registerName);
ClearValue<SomeInterface>(iocContainer, registerName);
//after clear value
Resolve<SomeInterface>(iocContainer, registerName);
}
private static void Resolve<T>(UnityContainer iocContainer,string name)
{
if (iocContainer.IsRegistered<T>(name))
iocContainer.Resolve<T>(name);
iocContainer.ResolveAll<T>();
}
private static void ClearValue<T>(UnityContainer iocContainer, string name)
{
foreach (var registration in iocContainer.Registrations.Where(p => p.RegisteredType == typeof(T)
&& p.Name==name))
{
registration.LifetimeManager.RemoveValue();
}
}
If you debug it, you will see that after the call to ClearValue, the container still says it is registered, but if you try to resolve that instance it will throw an exception. What is even worse, calls to ResolveAll<T> will fail too.
To Sum up, no matter if you do ClearValue, wrap around your register instance with another IoC or a custom class, or provide your own LifeTimeManager, ResolveAll<T> and IsRegistered<T> won´t behave as expected, and the registration will still be there. So don't try it because it won´t work and it will cause problems down the road.
I think that is what you are looking for.
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Here is how I handled unregistering instances from a unity container
I needed to implement Add/Remove functionality like this:
public interface IObjectBuilder
{
void AddInstance<T>(T instance);
void RemoveInstance<T>(T instance);
}
I created a custom lifetime manager to do the implementation
public class ExplicitLifetimeManager :
LifetimeManager
{
object Value;
public override object GetValue()
{
return Value;
}
public override void SetValue(object newValue)
{
Value = newValue;
}
public override void RemoveValue()
{
Value = null;
}
}
Here is the final implementation:
Dictionary<object, ExplicitLifetimeManager> Instances = new Dictionary<object, ExplicitLifetimeManager>();
public void AddInstance<T>(T instance)
{
ExplicitLifetimeManager e = new ExplicitLifetimeManager();
Instances[instance] = e;
Container.RegisterInstance(instance, e);
}
public void RemoveInstance<T>(T instance)
{
Instances[instance].RemoveValue();
Instances.Remove(instance);
}
calling removevalue on the custom lifetime manager causes the instance to be unregistered
I have the same challenge and after experimenting I solved it by using the standard ContainerControlledLifetimeManager and calling RemoveValue when I want to remove the container instance. Note that if you are not using interfaces and your object has constructor which the container can find and use it will recreate the instance after you have destroyed it with lifetimeManager.RemoveValue().
[TestClass]
public class UnityContainerTest
{
[TestMethod]
public void RemoveFromContainer()
{
UnityContainer container = new UnityContainer();
MyUnityMember member = new MyUnityMember(5);
LifetimeManager lifetimeManager = new ContainerControlledLifetimeManager();
container.RegisterInstance(member, lifetimeManager);
var resolved = container.Resolve<MyUnityMember>();
Assert.IsNotNull(resolved);
lifetimeManager.RemoveValue();
try
{
resolved = container.Resolve<MyUnityMember>();
Assert.Fail(resolved + " is still in the container");
}
catch (ResolutionFailedException)
{
}
}
public class MyUnityMember
{
public MyUnityMember(int x)
{
I = x;
}
public int I { get; private set; }
}
}
I had a similar requirement whereby I wanted to temporarily store objects in the unity container and found this was not possible (or at least easily possible).
If your objective is to have a temporary storage place easily available to unity, then create a temporary storage service.
public class TemporaryStorageService : ITemporaryStorageService
{
public void Deposit<T>(Object o, string key)
{
System.Windows.Application.Current.Properties[key] = o;
}
public T Withdraw<T>(string key)
{ T o = (T)System.Windows.Application.Current.Properties[key];
System.Windows.Application.Current.Properties.Remove(key);
return o;
}
}
Register your service with Unity. Then when you wish to store an object you call the Deposit Method and when you wish to remove the object you call the Withdraw method.
A fuller explanation can be found here

Fake ASMX Web Service Call

I built a .NET ASMX web service connecting to an SQL Server database. There is a web service call GetAllQuestions().
var myService = new SATService();
var serviceQuestions = myService.GetAllQuestions();
I saved the result of GetAllQuestions to GetAllQuestions.xml in the local application folder
Is there any way to fake the web service call and use the local xml result?
I just want to take the contents of my entire sql table and have the array of objects with correlating property names automatically generated for me just like with LINQ to SQL web services.
Please keep in mind that I am building a standalone Monotouch iPhone application.
Use dependency injection.
//GetSATService returns the fake service during testing
var myService = GetSATService();
var serviceQuestions = myService.GetAllQuestions();
Or, preferably, in the constructor for the object set the SATService field (so the constructor requires the SATService to be set. If you do this, it will be easier to test.
Edit: Sorry, I'll elaborate here. What you have in your code above is a coupled dependency, where your code creates the object it is using. Dependency injection or the Inversion of Control(IOC) pattern, would have you uncouple that dependency. (Or simply, don't call "new" - let something else do that - something you can control outside the consumer.)
There are several ways to do this, and they are shown in the code below (comments explain):
class Program
{
static void Main(string[] args)
{
//ACTUAL usage
//Setting up the interface injection
IInjectableFactory.StaticInjectable = new ConcreteInjectable(1);
//Injecting via the constructor
EverythingsInjected injected =
new EverythingsInjected(new ConcreteInjectable(100));
//Injecting via the property
injected.PropertyInjected = new ConcreteInjectable(1000);
//using the injected items
injected.PrintInjectables();
Console.WriteLine();
//FOR TESTING (normally done in a unit testing framework)
IInjectableFactory.StaticInjectable = new TestInjectable();
EverythingsInjected testInjected =
new EverythingsInjected(new TestInjectable());
testInjected.PropertyInjected = new TestInjectable();
//this would be an assert of some kind
testInjected.PrintInjectables();
Console.Read();
}
//the inteface you want to represent the decoupled class
public interface IInjectable { void DoSomething(string myStr); }
//the "real" injectable
public class ConcreteInjectable : IInjectable
{
private int _myId;
public ConcreteInjectable(int myId) { _myId = myId; }
public void DoSomething(string myStr)
{
Console.WriteLine("Id:{0} Data:{1}", _myId, myStr);
}
}
//the place to get the IInjectable (not in consuming class)
public static class IInjectableFactory
{
public static IInjectable StaticInjectable { get; set; }
}
//the consuming class - with three types of injection used
public class EverythingsInjected
{
private IInjectable _interfaceInjected;
private IInjectable _constructorInjected;
private IInjectable _propertyInjected;
//property allows the setting of a different injectable
public IInjectable PropertyInjected
{
get { return _propertyInjected; }
set { _propertyInjected = value; }
}
//constructor requires the loosely coupled injectable
public EverythingsInjected(IInjectable constructorInjected)
{
//have to set the default with property injected
_propertyInjected = GetIInjectable();
//retain the constructor injected injectable
_constructorInjected = constructorInjected;
//using basic interface injection
_interfaceInjected = GetIInjectable();
}
//retrieves the loosely coupled injectable
private IInjectable GetIInjectable()
{
return IInjectableFactory.StaticInjectable;
}
//method that consumes the injectables
public void PrintInjectables()
{
_interfaceInjected.DoSomething("Interface Injected");
_constructorInjected.DoSomething("Constructor Injected");
_propertyInjected.DoSomething("PropertyInjected");
}
}
//the "fake" injectable
public class TestInjectable : IInjectable
{
public void DoSomething(string myStr)
{
Console.WriteLine("Id:{0} Data:{1}", -10000, myStr + " For TEST");
}
}
The above is a complete console program that you can run and play with to see how this works. I tried to keep it simple, but feel free to ask me any questions you have.
Second Edit:
From the comments, it became clear that this was an operational need, not a testing need, so in effect it was a cache. Here is some code that will work for the intended purpose. Again, the below code is a full working console program.
class Program
{
static void Main(string[] args)
{
ServiceFactory factory = new ServiceFactory(false);
//first call hits the webservice
GetServiceQuestions(factory);
//hists the cache next time
GetServiceQuestions(factory);
//can refresh on demand
factory.ResetCache = true;
GetServiceQuestions(factory);
Console.Read();
}
//where the call to the "service" happens
private static List<Question> GetServiceQuestions(ServiceFactory factory)
{
var myFirstService = factory.GetSATService();
var firstServiceQuestions = myFirstService.GetAllQuestions();
foreach (Question question in firstServiceQuestions)
{
Console.WriteLine(question.Text);
}
return firstServiceQuestions;
}
}
//this stands in place of your xml file
public static class DataStore
{
public static List<Question> Questions;
}
//a simple question
public struct Question
{
private string _text;
public string Text { get { return _text; } }
public Question(string text)
{
_text = text;
}
}
//the contract for the real and fake "service"
public interface ISATService
{
List<Question> GetAllQuestions();
}
//hits the webservice and refreshes the store
public class ServiceWrapper : ISATService
{
public List<Question> GetAllQuestions()
{
Console.WriteLine("From WebService");
//this would be your webservice call
DataStore.Questions = new List<Question>()
{
new Question("How do you do?"),
new Question("How is the weather?")
};
//always return from your local datastore
return DataStore.Questions;
}
}
//accesses the data store for the questions
public class FakeService : ISATService
{
public List<Question> GetAllQuestions()
{
Console.WriteLine("From Fake Service (cache):");
return DataStore.Questions;
}
}
//The object that decides on using the cache or not
public class ServiceFactory
{
public bool ResetCache{ get; set;}
public ServiceFactory(bool resetCache)
{
ResetCache = resetCache;
}
public ISATService GetSATService()
{
if (DataStore.Questions == null || ResetCache)
return new ServiceWrapper();
else
return new FakeService();
}
}
Hope this helps. Good luck!
when you say fake the call, are you just testing the client side?
you could use fiddler, intercept the request and return the local xml file to the client. No messing around with your client code then.
To elaborate on Audie's answer
Using DI would get you what you want. Very simply you would create an interface that your real object and your mock object both implement
public interface IFoo
{}
Then you would have your GetSATService method return either a MockSATSerivce or the real SATService object based on your needs.
This is where you would use a DI container (some object that stores interface to concrete type mappings) You would bootstrap the container with the types you want. So, for a unit test, you could contrstruct a mock container that registers the MockSATService as the implementer of the IFoo interface.
Then you would as the container for the concrete type but interface
IFoo mySATService = Container.Resolve<IFoo>();
Then at runtime you would just change out the container so that it bootstraps with the runtime types instead of the mock types but you code would stay the same (Because you are treating everything as IFoo instead SATService)
Does that make sense?
Over time I found that an interesting way to do this is by extracting an interface and creating a wrapper class. This adapts well to a IoC container and also works fine without one.
When testing, create the class passing a fake service. When using it normally, just call the empty constructor, which might simply construct a provider or resolve one using a config file.
public DataService : IDataService
{
private IDataService _provider;
public DataService()
{
_provider = new RealService();
}
public DataService(IDataService provider)
{
_provider = provider;
}
public object GetAllQuestions()
{
return _provider.GetAllQuestions();
}
}

Categories