How to avoid passing around runtime parameter everywhere - c#

I have a client app that let's user take part in a match. In almost all cases, maybe except tests, user takes part in one or zero matches at the same time. Every match have a unique ID, let's call it MatchID. I have many services that provides information about the match, e.g.:
interface IMatchPlayersRepository
{
string[] GetMatchPlayers(string matchId);
string GetBestPlayer(string matchId);
}
interface IMatchFieldsInfo
{
int GetFieldSize(string matchId);
}
interface IMatchScoreboardProvider
{
Scoreboard GetScoreboard(string matchId, string someOtherParam);
}
// And many others...
Implementations of those use one another, e.g.:
public class MatchScoreboardProvider : IMatchScoreboardProvider
{
public MatchScoreboardProvider(IMatchPlayersRepository playersRepository)
{ //...
}
public Scoreboard GetScoreboard(string matchId, string someOtherParam)
{
var bestPlayer = _playersRepository.GetBestPlayer(matchId);
//...
}
}
How do I prevent passing matchId everywhere? Using factories only moves the problem to factory methods, e.g.:
public class MatchPlayersRepositoryFactory
{
public IMatchPlayersRepository Get(string matchId) => new MatchPlayersRepository(matchId);
}
public class MatchScoreboardProvider : IMatchScoreboardProvider
{
// Created from factory
public MatchScoreboardProvider(string matchId, MatchPlayersRepositoryFactory playersRepositoryFactory)
{ //...
}
public Scoreboard GetScoreboard(string someOtherParam)
{
var bestPlayer = _playersRepositoryFactory.Get(_matchId).GetBestPlayer();
//...
}
}
Ideally, I would have another DI "composition root" for every match, where all object are created from this new DI framework, that passes matchId to them. However, creating a new "composition root" seems like a really bad idea, from what I understand.

Related

Strategy pattern or no strategy pattern?

Without entering in academic definitions, let's say that the Strategy Pattern is used when you have a client code (Context) which will execute an operation, and this operation could be implemented in different ways (algorithms). For instance: https://www.dofactory.com/net/strategy-design-pattern
Which Strategy (or algorithm) will be used depend on many occasions of some input conditions. That is why Strategy Pattern sometimes is used in combination with Factory Pattern. The Client pass the input conditions to the Factory. Then the Factory knows which Strategy has to create. Then the Client execute the operation of the Strategy created.
However, I have come across in several occasions with a problem that seems to me the opposite. The operation to be execute is always the same, but it would be only executed depending on a family of input conditions. For example:
public interface IStrategy
{
string FileType { get; }
bool CanProcess(string text);
}
public class HomeStrategy : IStrategy
{
public string FileType => ".txt";
public bool CanProcess(string text)
{
return text.Contains("house") || text.Contains("flat");
}
}
public class OfficeStrategy : IStrategy
{
public string FileType => ".doc";
public bool CanProcess(string text)
{
return text.Contains("office") || text.Contains("work") || text.Contains("metting");
}
}
public class StragetyFactory
{
private List<IStrategy> _strategies = new List<IStrategy>{ new HomeStrategy(), new OfficeStrategy() };
public IStrategy CreateStrategy(string fileType)
{
return _strategies.Single(s => s.FileType == fileType);
}
}
Now the client code will get the files from some repository and will save the files in the database. This is the operation, store the files in the database, just depending on the type of the file and the specific conditions for each file.
public class Client
{
public void Execute()
{
var files = repository.GetFilesFromDisk();
var factory = new StragetyFactory();
foreach (var file in files)
{
var strategy = factory.CreateStrategy(file.Type);
if (strategy.CanProcess(file.ContentText))
{
service.SaveInDatabase(file);
}
}
}
}
Am I wrong to believe that this is a different pattern than the Strategy Pattern? (even though I have called Strategy in the code above because I have seem it like this in several occasions)
If this problem is different than the one the Strategy Pattern solves, then which pattern is it?.
Not really a strategy pattern, because as definition in the strategy pattern in Wikipedia says:
In computer programming, the strategy pattern (also known as the
policy pattern) is a behavioral software design pattern that enables
selecting an algorithm at runtime. Instead of implementing a single
algorithm directly, code receives run-time instructions as to which in
a family of algorithms to use.[1]
You're not selecting an algorithm to execute at runtime, you just check conditions to see if file type satisfies conditions and then execute the algorithm.
Do you expect this to change ever ? Do you need this to be extensible, so that in the future if you need to execute different code based on file type you can do it easily.
If answer to those questions is yes, then you can keep strategies and apply few changes.
First define base strategy class that defines the code to execute
public abstract class StrategyBase
{
public abstract bool CanProcess(string fileType);
public virtual void Execute(File file)
{
_service.SaveInDatabase(file);
}
}
Your strategies change to derive from base
public class HomeStrategy : StrategyBase
{
public string FileType => ".txt";
public override bool CanProcess(string text)
{
return text.Contains("house") || text.Contains("flat");
}
}
// implement the same for the rest of strategies...
As mentioned in the comment, it's not really a factory as it doesn't create a new strategy on every call. It's more like a provider which provides strategy to execute based on file type.
public class StragetyProvider
{
private List<StrategyBase> _strategies = new List<StrategyBase>{ new HomeStrategy(), new OfficeStrategy() };
public StrategyBase GetStrategy(string fileType)
{
return _strategies.FirstOrDefault(s => s.CanProcess(fileType));
}
}
As a result client code became much simpler:
public class Client
{
public void Execute()
{
var files = repository.GetFilesFromDisk();
var provider = new StragetyProvider();
foreach (var file in files)
{
var strategy = provider.GetStrategy(file.Type);
strategy?.Execute(file);
}
}
}
Notice, when you need to add new condition, you just implement a new class that derives from StrategyBase and add it to the list of strategies in the provider and no other changes required. If you would need to execute different logic for some new file type, you will create new strategy and override Execute method and that's it.
If this does really look like an overkill and you don't need to ever extend this solution with new behavior & the only thing you want is to be able to add new condition then go with another approach.
public interface ISatisfyFileType
{
bool Satisfies(string fileType);
}
public class HomeCondition : ISatisfyFileType
{
public string FileType => ".txt";
public bool Satisfies(string text)
{
return text.Contains("house") || text.Contains("flat");
}
}
// the rest of conditions
Compose all conditions into one
public class FileConditions
{
private List<ISatisfyFileType> _conditions = new List<ISatisfyFileType>{ new HomeStrategy(), new OfficeStrategy() };
public bool Satisfies(string fileType) =>
_conditions.Any(condition => condition.Satisfies(fileType));
}
And the client:
public class Client
{
public void Execute()
{
var files = repository.GetFilesFromDisk();
var fileTypeConditions = new FileConditions();
foreach (var file in files)
{
if (fileTypeConditions.Satisfies(file.ContentText))
{
service.SaveInDatabase(file);
}
}
}
}
This also has the benefit of implementing a new condition and adding it to FileConditions class should you need a new condition without touching client code.

Where to inject a dependent component which has already a constructor

I have a few business objects that have to be used together to get a specific outcome. Take a look at the following very simplyfied example for reference.
My question is: how do I get a reference to the agent using DI in the Station class ? I mostly prefer constructor injection, but that is not possible the Station class already has a stationCode as a required item.
Any ideas ?
Usage:
var station1 = new Station("xx");
var station2 = new Station("yy");
var route = new Route(station1, station2);
var length = route.GetLength();
public class Location
{
public int Position {get; set;}
}
public interface IAgent
{
Location GetLocation(string stationCode);
}
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public Location GetLocation()
{
// issue here: how to get a reference to the agent instance using DI
_agent.GetLocation(_stationCode);
}
}
public class Route
{
private Station _station1;
private Station _station2;
public Route(Station station1, Station station2)
{
_station1 = station1;
_station2 = station2;
}
public int GetLength()
{
var location1 = _station1.GetLocation();
var location2 = _station2.GetLocation();
result = location2.Position - location1.Position;
return result;
}
}
Your classes seem to be having an identity crisis. When using DI, you should have just 2 types of classes to deal with - injectables and newables. Your Station class seems like a kludge because it both provides a service (has dependencies) and has state. To make your classes DI-friendly, you should design classes that only provide state to classes that only do something with the state (services).
Route
This class is injectable - that is, it should be wired from the DI container.
public interface IRoute
{
int GetLength(Station station1, Station station2);
}
public class Route : IRoute
{
private readonly IAgent _agent;
public Route(IAgent agent)
{
if (agent == null) throw new ArgumentNullException("agent");
_agent = agent;
}
public int GetLength(Station station1, Station station2)
{
var location1 = _agent.GetLocation(station1.StationCode);
var location2 = _agent.GetLocation(station2.StationCode);
result = location2.Position - location1.Position;
return result;
}
}
Station
This class is newable - that is, you should always use the new keyword to instantiate it.
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public string StationCode
{
get { return _stationCode; }
// Optional: provide setter here
}
}
Usage
var station1 = new Station("xx");
var station2 = new Station("yy");
// IRoute is injected where you need to make the calculation
var length = _route.GetLength(station1, station2);
Perhaps it would be better to rename Route to something more appropriate, since it does not provide a route, it calculates the route length.
Frankly, if your Station class doesn't have any other state than a single string variable, it would probably make more sense to eliminate the class and just use strings for station1 and station2. But this is mostly just a matter of personal taste.
The concept of two types of classes to deal with, injectables and newables, is a good idea. But when newables should contain only limited business logic, you are drifting away from pure object-oriented concepts. When you write code for a complex domain model, your newable business classes contain both business logic and data. That´s also the intention of the question, I assume. The Station and Route classes are simple examples that contain much more logic and data in reality.
So I would suggest to have better separation of concerns, by separating code for storage from you business logic. I see two common solutions for this.
When data is loaded in memory, a separate StationStore class is an injectable that loads stations and stores them in the context of the business domain, eg. in a static property:
public IEnumarable<Station> Station.Store { get; internal set; }
All DI code can be hidden in a business base class. It´s less disturbing to put DI dependencies there. So an agent can be resolved in the generic base class based on the template types provided.
public class Station : BusinessClass<Station, StationAgent>
{
public string StationCode { get; internal set; }
public Location Location { get; internal set; }
public Station(string stationCode)
{
base.Load(stationCode, this);
}
}

Register Multiple Email Output Services using Simple Injector

I am using the excellent Simple Injector Ioc framework and would like to "plug in" multiple email output services ie Mandrill, MailChimp etc
My question really is am I doing this correctly as it results in a Cast at my send method.
So I have a simple IEmailOutputService
public interface IEmailOutputService
{
string Identifier { get; }
bool Send(object message, object contents);
}
And a MandrillOutputService (shortened)
public class MandrillOutputService : IEmailOutputService
{
public MandrillOutputService()
{
//DI stuff here
}
public string Identifier => "Mandrill";
public bool Send(EmailMessage message, IEnumerable<TemplateContent> templateContents)
{
if (message == null)
return false;
//send code here
return true;
}
bool IEmailOutputService.Send(object message, object contents)
{
//TODO this doesnt look right!!
var m = message as EmailMessage;
var c = contents as IEnumerable<TemplateContent>;
//forwards method onto bespoke Mandrill Send method above
return Send(m, c);
}
}
I have an EmailContext that gets the Email Output Provider for the logged in User eg "Mandrill" heres the IEmailContext
public interface IEmailContext
{
string GetProvider();
}
EmailOutputComposite is used to select correct Email Output Service
public class EmailOutputComposite : IEmailOutputService
{
private readonly IEmailContext _emailContext;
private readonly IEnumerable<IEmailOutputService> _emailOutputServices;
public string Identifier => "EmailOutputComposite";
public EmailOutputComposite(
IEmailContext emailContext, IEnumerable<IEmailOutputService> emailOutputServices)
{
this._emailContext = emailContext;
this._emailOutputServices = emailOutputServices;
}
bool IEmailOutputService.Send(object message, object contents) =>
this._emailOutputServices
.FirstOrDefault(x => x.Identifier.ToLower() == this._emailContext.GetProvider())
.Send(message, contents);
}
and finally registrations in Simple Injector
container.RegisterCollection(typeof(IEmailOutputService), new[]
{
typeof(MandrillOutputService)
//other emailOutputServices to go here
});
container.Register(typeof(IEmailOutputService), typeof(EmailOutputComposite),
Lifestyle.Singleton);
So my question is am I doing this correctly or is there a better way. I have to get the Users Email Provider (Mandrill) from Database so cant think of another way to do this but was concerned with the Cast I have to do in MandrillOutputService.Send method.
Wouldn't it be simpler to use the Strategy and Factory patterns, forgive me I'm going to change the implementation a bit:
For container registrations:
container.Register<EmailProviderFactory>(Lifestyle.Scoped);
container.Register<MandrillOutputService>(Lifestyle.Scoped);
container.Register<OtherOutputService>(Lifestyle.Scoped);
Then use a factory to resolve my email providers:
public class EmailProviderFactory
{
private readonly Container container;
public EmailProviderFactory(Container container)
{
this.container = container;
}
public IEmailOutputService Create(string provider)
{
switch (provider)
{
case "Mandrill": // should be in a constants class
return container.GetInstance<MandrillOutputService>();
case "Other": // should be in a constants class
return container.GetInstance<OtherOutputService>();
default: throw new ArgumentOutOfRangeException("provider");
}
}
}
I've changed the IEmailOutputService to have one method with explicit types:
public interface IEmailOutputService
{
bool Send(EmailMessage message, IEnumerable<TemplateContent> contents);
}
The email providers :
public class MandrillOutputService : IEmailOutputService
{
public bool Send(EmailMessage message, IEnumerable<TemplateContent> templateContents)
{
// ...
}
}
public class OtherOutputService : IEmailOutputService
{
public bool Send(EmailMessage message, IEnumerable<TemplateContent> templateContents)
{
// ...
}
}
Usage:
foreach(var userEmailProvider in UserEmailProviders) {
// I'm assuming the factory is injected
var emailService = _emailProviderFactory.Create(userEmailProvider.Name);
emailService.Send(new EmailMessage(), new List<TemplateContent>());
}
I do not think you need IEmailContext or a EmailOutputComposite. By using the EmailProviderFactory you will only create a specific provider when you need it.
I see two problems in your design:
You are violating the Liskov Substitution Principle in your MandrillOutputService by accepting only a subset of the accepted types of the IEmailOutputService abstraction; this might cause the appliation to break at runtime when the user supplies values that are invalid for that specific implementation.
The Identifier property on the IEmailOutputService violates the Interface Segration Principle, because it is a method that consumers don't use. The only class that is actually interested in this property is the EmailOutputComposite. Removing the Identifier from the abstraction has the advantage that it can simplify unit testing, since there is less code that a consumer can call. It also simplifies the interface, which is always a good thing.
I'm unsure how to fix the LSP principle, because its unclear to me how other implementations look like.
With respect to the ISP violation, you can do the following to fix it:
Mark the implementations instead with an attribute that defines their Identifier. This allows you to remove the property from the interface, but the downside is that the Composite can only filter those services in case the actual types are injected (and not decorated, because that disallows you from retrieving those attributes).
You let the Composite depend on the actual concrete implementations and implement a switch-case statement inside the Composite. This again allows you to remove the property from the interface, but downside is that you will have to update the composite every time a new implementation is added (which might not be that bad if you consider the Composite part of your Composition Root).
You define a dictionary of IEmailOutputServices during the registration process, where the Identifier is the dictionary's key. This removes the need to have the Identifier as part of the abstraction, but also removes the identifier from the implementation (which might actually be something good).
Here's an example of this last example:
container.RegisterSingleton<IEmailOutputService, EmailOutputComposite>();
container.RegisterSingleton(new Dictionary<string, Func<IEmailOutputService>>()
{
"Mandrill", CreateEmailServiceProducer<MandrillOutputService>(container),
"other", CreateEmailServiceProducer<Other>(container),
// ..
});
privte static Func<IEmailOutputService> CreateEmailServiceProducer<T>(Container c)
where T : IEmailOutputService =>
Lifestyle.Transient.CreateProducer<IEmailOutputService, T>(c).GetInstance;
Where the Composite is implemented as follows:
public class EmailOutputComposite : IEmailOutputService
{
private readonly IEmailContext _emailContext;
private readonly Dictionary<string, Func<IEmailOutputService>> _emailOutputServices;
public EmailOutputComposite(
IEmailContext emailContext,
Dictionary<string, Func<IEmailOutputService>> emailOutputServices)
{
_emailContext = emailContext;
_emailOutputServices = emailOutputServices;
}
public bool Send(object m, object c) => Service.Send(m, c);
IEmailOutputService Service => _emailOutputServices[_emailContext.GetProvider()]();
}
Whether or not this is actually an improvement is up to you.

Creating Object on the basis of type base on a condition

I am facing a unique problem. We have a download functionality in our application in which we have a drop-down which contains type of file user need to download i.e. pdf,csv or excel
To implement this problem we have create one Interface IFileDownaload and three different class clsCSV,ClsPDF and clsExcel which are implemented by IFileDownaload
Now my problem is how to inititate a class on the basis of Dropdown value because i dont want to write down if-else statement
if(option=="pdf") type
because in future if we introduce a new file download type then it will impact us to re-write whole logic again
Any suggestion
You can define abbreviation for each class you have, so that you'll have something like this:
public interface IFileDownload
{
string Abbreviation { get; }
}
public class PDFDonwload : IFileDownload
{
public string Abbreviation { get; private set; }
}
Then you can make some class, i.e. factory, which have instances of all filedownloaders you have and which iterates through their Abbreviations till it finds proper class. It can be implemented like this:
public static class DownloadHander
{
private static List<IFileDownload> _handlers;
static DownloadHander()
{
_handlers = new List<IFileDownload>();
}
public static void Initialize()
{
_handlers.Add(new PDFDonwload());
}
public static Stream HandleDownload(string abbreviation)
{
foreach (var fileDownload in _handlers)
{
if (fileDownload.Abbreviation == abbreviation)
{
//and here you make a stream for client
}
}
throw new Exception("No Handler");
}
}
When I have a number of classes which implement a certain type and those classes are stateless services rather than entities, I use a Registry rather than a Factory.
Your Registry has instances of all the IFileDownload-implementing classes injected into it in an array:
public class FileDownloaderRegistry
{
private readonly IFileDownload[] _downloaders;
public FileDownloaderRegistry(IFileDownload[] downloaders)
{
_downloaders = downloaders;
}
}
You then have a property on IFileDownload which indicates the file type handled by the downloader:
public interface IFileDownload
{
string FileType { get; }
// etc.
}
And finally a method on your Registry which takes the file type and delegates the work to the appropriate downloader:
public string DownloadFile(string fileName, string fileType)
{
var handlingDownloader = _downloaders
.FirstOrDefault(d => d.FileType == fileType);
if (handlingDownloader == null)
{
// Probably throw an Exception
}
return handlingDownloader.Download(fileName);
}
DI containers will often implicitly understand arrays, so just registering the various IFileDownloads should end up with them in the array injected into the Registry's constructor. e.g. with StructureMap you use:
For<IFileDownload>().Use<ClsCSV>();
For<IFileDownload>().Use<ClsPDF>();
For<IFileDownload>().Use<ClsExcel>();
Adding a new IFileDownload is then a matter of writing the class and adding it to the set of IFileDownloads registered with your DI container. You can also have the container manage the lifetimes of each object so (if they're stateless) they're only instantiated once each, when they're first needed.

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