C# switch library using with program paremeters - c#

I have a project with two class libraries.
I need to switch between them programatically, with application parameters, something like
if(arg == "a")
using LibraryA;
if(arg == "b")
using LibraryB;
namespace Project
{
public class MyClass
{
// my code here
}
}

If you want to build loose-couple application, i suggest you read more about Dependancy Injection pattern.
This is a nice article, desscribed how to build such design. (First 4 lessons)

This is quite a complex requirement and you'll have to bring together multiple patterns & practices to get through this. I'll try and link off to the relevant principles as I go along.
The first problem to tackle is aligning the two class libraries such that they have a common interface. This is necessary in order to make them interchangeable as you describe. Usually this would be as simple as creating an interface that both objects implement - but you mentioned that you only have control over one of the libraries. In that case you need to utilize the adapter pattern to coerce the library you don't have control over to implement your common interface.
Say we currently have these two classes in Library1.dll and Library2.dll (Library1.dll is the one we have control over)...
// in Library1.dll
public class Foo
{
public int DoSomething() { ... }
}
// In Library2.dll
public class Foo
{
public int DoSomething() { ... }
}
First we need to define our common interface. This should reside in a core/shared library...
// In Shared.dll
public interface IFoo
{
int DoSomething();
}
Now because we have control over library one, we can easily make it implement the common interface in the usual way...
// In Library1.dll
public class Foo : IFoo
{
public int DoSomething() { ... }
}
However because we don't have control over Library2.dll we'll need to create an adapter class. The purpose of this class is simply to implement the common interface, and all behaviour is delegated to the real Library2.Foo. In effect this allows us to make the Library2.Foo object implement our common interface.
// In Shared.dll
public class Foo2Adapter : IFoo()
{
private Library2.Foo _realFoo;
public Foo2Adapter()
{
_realFoo= new Library2.Foo();
}
public int DoSomething()
{
_realFoo.DoSomething();
}
}
Now we need to modify all of our client code to use the common interface rather than the objects directly. Where before you might have had something like this...
if(arg == "a")
using LibraryA;
if(arg == "b")
using LibraryB;
namespace Project
{
public class MyClass
{
public void Bar()
{
var foo = new Foo();
foo.DoSomething();
}
}
}
Now your code should only use the interface...
namespace Project
{
public class MyClass
{
public void Bar(IFoo foo)
{
foo.DoSomething();
}
}
}
Now we have a new problem, how do we know which version of IFoo to use? Is it Library1.Foo, or Shared.Foo2Wrapper?
You can use dependency injection to solve this problem. An inversion of control container will provide objects for you, and you can configure it to provide different kinds of objects based on certain conditions. Here's a psuedocode example using a sytax similar to that used by StructureMap (my personal favourite IoC container)...
var container = new IocContainer();
if (arg == "a")
container.For<IFoo>().Use<Library1.Foo>();
else if (arg == "b")
container.For<IFoo>().Use<Shared.Foo2Adapter>();
var foo = container.GetInstance<IFoo>();
Now when we call GetInstance<IFoo>() the IoC container will give us back either a Library1.Foo or a Shared.Foo2Wrapper depending on how it was configured by the command line. We now need to go through all the places in our client code where we previously had new Foo() and replace it with container.GetInstance<IFoo>().
I hope that gets you moving :)

Here's an example of how you can achieve what you're after.
using System;
namespace StackOverflowDemo.Applications.TestFrameworkDemo.Data
{
public interface IDataSource
{
string GetTitle(int id);
}
public class Database: IDataSource
{
public string GetTitle(int id)
{
string result;
//logic to connect to a database and retrieve a value would go here
switch (id)
{
case 1: result = "DB First Title"; break;
case 2: result = "DB Second Title"; break;
default: throw new KeyNotFoundException(string.Format("ID '{0}' not found",id));
}
return result;
}
}
}
using System;
using StackOverflowDemo.Applications.TestFrameworkDemo.Data;
namespace StackOverflowDemo.Applications.TestFrameworkDemo.DataTest
{
public class DatabaseMock : IDataSource
{
public string GetTitle(int id)
{
string result;
switch (id)
{
case 1: result = "DBMock First Title"; break;
case 2: result = "DBMock Second Title"; break;
default: throw new KeyNotFoundException(string.Format("ID '{0}' not found", id));
}
return result;
}
}
}
using System;
using StackOverflowDemo.Applications.TestFrameworkDemo.Data;
namespace StackOverflowDemo.Applications.TestFrameworkDemo.Logic
{
public class SomeBusinessObject
{
private IDataSource myData;
public SomeBusinessObject(IDataSource myData)
{
this.myData = myData;
}
public void OutputTitle(int id)
{
Console.WriteLine(myData.GetTitle(id));
}
}
}
using System;
using StackOverflowDemo.Applications.TestFrameworkDemo.Data;
//using StackOverflowDemo.Applications.TestFrameworkDemo.DataTest; //we don't need the using statement if we use the whole path below, which I think relates to your question
using StackOverflowDemo.Applications.TestFrameworkDemo.Logic;
namespace StackOverflowDemo.Applications.TestFrameworkDemo
{
class Program
{
public static void Main(string[] args)
{
IDataSource myData;
#if(DEBUG)
myData = new StackOverflowDemo.Applications.TestFrameworkDemo.DataTest.DatabaseMock();
#else
myData = new Database();
#endif
SomeBusinessObject sbo = new SomeBusinessObject(myData);
sbo.OutputTitle(1);
Console.WriteLine("Done");
Console.ReadKey();
}
}
}
More info on mocks is available here: http://msdn.microsoft.com/en-us/library/ff650441.aspx
There's also a load of stuff at Channel9: http://channel9.msdn.com/search?term=test+driven+development
Alternatively you may be interested in this: http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx. It allows you to hijack methods of existing objects and replace them with dummy methods. I've not yet played with this, but it looks promising.

Related

Using Dependency Injection for classes instantiated at run time

I have two classes: ImportBase.cs (Parent) and ImportFleet.cs (Child) which will in the future import a CSV file. Each child of ImportBase will implement a different implementation of the actual import code.
The approriate child class to use is determined in a Service class where the correct class is instantiated and the import method called. All is going well up until this point.
The problem is that I also want to Dependency Inject some repository classes into ImportBase and it's inherited classes (as I have attempted in the code below):
ImportBase.cs
namespace WebApi.Services.Import.Investments
{
interface IImport
{
public void Import(IFormFile file, int UserId);
}
public abstract class ImportBase : IImport
{
public abstract void Import(IFormFile file, int UserId);
protected List<InvestmentTransactionType> transactionTypes = new();
protected IInvestmentEntityRepository _investmentEntityRepository;
public ImportBase(IInvestmentEntityRepository investmentEntityRepository)
{
_investmentEntityRepository = investmentEntityRepository;
}
}
}
ImportFleet.cs
namespace WebApi.Services.Import.Investments
{
public class ImportFleet : ImportBase
{
public ImportFleet(IInvestmentEntityRepository investmentEntityRepository) : base(investmentEntityRepository)
{
}
public override void Import(IFormFile file, int UserId)
{
}
}
}
InvestmentService.cs
namespace WebApi.Services
{
public interface IInvestmentService
{
public void Import(IFormFile file, int UserId, int InvestmentEntityId);
}
public class InvestmentService: IInvestmentService
{
public void Import(IFormFile file, int UserId, int InvestmentEntityId)
{
IImport importService = null;
string investmentEntity = ImportBase.determineInvestmentEntityFromCsv(file);
switch(investmentEntity)
{
case "fleet":
importService = new ImportFleet(); // problem is here
break;
}
if (importService != null)
{
importService.Import(file, UserId);
}
}
}
}
The problem is the following line:
importService = new ImportKuflink();
Because I only determine which child class to instantiate at run time, I cannot take advantage of DI here.
Under normal circumstances I would make the Import classes a DI based service so all dependencies are available, however I have to create the instance at run time so this I don't think is possible.
Is there a way to accomplish the above?
Here's a simplified version of your code that demonstrates how you can populate an instance of an object from a DI service container.
In your InvestmentService:
Inject the IServiceProvider.
Use the little known utility ActivatorUtilities to get a fully DI'd instance of your object.
Make sure you dispose it properly if it implemenents IDisposable. I've included an async version if you use anything that needs a IAsyncDisposable.
public class InvestmentService : IInvestmentService
{
private IServiceProvider _serviceProvider;
public InvestmentService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
//...
}
public Import()
{
IImport? importService = null;
IDisposable? disposable = null;
var importFleet = ActivatorUtilities.CreateInstance<ImportFleet>(_serviceProvider);
if (importFleet is IDisposable)
disposable = importFleet as IDisposable;
importService = importFleet as IImport;
// Do whatever you want to do with it
disposable?.Dispose();
}
public async ValueTask ImportAsync()
{
IImport? importService = null;
IDisposable? disposable = null;
IAsyncDisposable? asyncDisposable = null;
var importFleet = ActivatorUtilities.CreateInstance<ImportFleet>(_serviceProvider);
if (importFleet is IDisposable)
disposable = importFleet as IDisposable;
if (importFleet is IAsyncDisposable)
asyncDisposable = importFleet as IAsyncDisposable;
importService = importFleet as IImport;
// Do whatever you want to do with it
disposable?.Dispose();
if (asyncDisposable is not null)
await asyncDisposable.DisposeAsync();
}
}
Yes, of course there is a way to accomplish this. But I guess the DI container you are using (like from MS) won't help you here.
I've been fiddling with crap like this for like two years so far and still am busy with it. Two years of creating my own IoC framework.
Usual DI/IoC microkernels follow OCP and other really mandatory concepts and patterns. What I've done is leaving one single small door open. I won't bore you with details. The fundamental idea is that a class must be decorated with the appropriate attributes in code, and then is able to call the microkernel within its constructor (which has been called by a simple "var foo = new Barney();") to let an entity be modified like it had been created by the microkernel.
There is no(t yet a) way to hook into the plain new() code. Some cheer this, some don't. I'm with the cheerleaders here. Why? Side-effects.
Imagine this:
public class SomeNumber
{
public int SomeValue { get; private set; }
public SomeNumber()
{
SomeValue = 19;
}
}
Okay? Let's assume you'd modified the new() process by whatever, then another user of your code goes:
Assert.AreEqual(19, someNumberEntity.SomeNumber);
and this code throws an exception, because for whatever reason your modifying code set the number to 7.
Now look at this code (from a unit test):
using System.Reflection;
using Kis.Core.Attributes;
namespace UnitTests_Kis.Core
{
[KisAware]
public class KisAwareSimpleClass
{
[Property(value: 123)]
public int ValueToCheck { get; set; } = 0;
[Property(value: "I am the doctor!")]
public string Name { get; set; } = "";
public KisAwareSimpleClass()
{
var t = this.GetType();
var fqtn = t.FullName;
var ec = new Kis.Core.EntityCreator(Assembly.GetAssembly(t));
ec.ModifyExistingEntity(fullyQualifiedTypeName: fqtn, existingEntity: this);
}
}
}
Clean code isn't always easily readable, but the aspects/attributes will raise coder's awareness.
PS: I posted the unit test code on purpose to show you what's happening.
Short version:
Microkernel.Modify(this);
You can inject a factory which has the services injected into it.
public interface IImportFactory
{
ImportFleet CreateFleetImporter();
}
public class MyImportFactory : IImportFactory
{
private readonly IMyDependency1 _dependency1;
private readonly IMyDependency2 _dependency2;
public MyImportFactory(IMyDependency1 dependency1, IMyDependency2 dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
public ImportFleet CreateFleetImporter()
{
return new ImportFleet(_dependency1, _dependency2);
}
}
Then inject the factory as a dependency in your Service class.

Mock testing scenarios when the method itself creates a class using a Factory method

See this example code below;
public Car {
public void BuildCar(CarType carType) {
var engineType = EngineTypeFactory.GetEngineType(carType);
var engineInsertionResult = InsertEngine(engineType);
if (!engineInsertionResult.IsRunning) {
throw new OhNoEngineFailedException("Engine Failure");
}
}
private EngineInsertionResult InsertEngine(EngineType engineType) {
var ignitionResult = engineType.TurnOn();
return new EngineInsertionResult() {
IsRunning: ignitionResult.IsEngineRunning;
}
}
}
public static EngineTypeFactory {
public EngineType GetEngineType(CarType carType) {
switch (carType) {
case carType.Petrol:
return EngineType.Petrol:
case carType.Electric:
return EngineType.Electric;
}
}
}
What's the best practice around testing the result (using Mocking) from the InsertEngine method to cover a scenario where it could return IsRunning as either true or false given that we create the EngineType using the factory method within the BuildCar method?!
I understand I could create the EngineType outside of the BuildCar method and pass that into the method to achieve, which is nice and simple but there's always a situation where I need to build the concrete classes using a Factory method and my head gets into a mess about if this the correct way or not?!
I was just wondering if there was a pattern I'm obviously missing or this is just the trade off for a scenario you can't really test unless you interface off the EngineTypeFactory and inject that into the Car class so that you can handle the GetEngineType return result directly? which seems excessive for testing purposes maybe?!

Resolving concrete types when using polymorphism in Autofac

Consider the following code:
public interface IFileBackup
{
Task Backup(byte[] file);
}
public class BackUpMechanismA : IFileBackup
{
//Implementation
public async Task Backup(byte[] file)
{
//Attempts to backup using mechanism A
}
}
public class BackUpMechanismB : IFileBackup
{
//Implementation
public async Task Backup(byte[] file)
{
//Attempts to backup using mechanism B
}
}
Then the calling class looks like this:
public class Caller
{
private readonly IFileBackup _backupA;
private readonly IFileBackup _backupB;
public Caller(IFileBackup backupA, IFileBackup backupB)
{
_backupA = backupA;
_backupB = backupB;
}
public async Task BackupFile(byte[] file)
{
try
{
await _backupA.Backup(file);
}
catch(SomeException)
{
await _backupB.Backup(file);
}
}
}
So what I'm trying to do here is to use polymorphism. So both BackupMechanismA and BackupMechanismB implements the Backup method in their own way. In the caller I want to attempt the first mechanism and if that doesn't work we catch an exception and try the second approach.
I'm having trouble resolving the correct implementations using Autofac. I have tried with:
builder.RegisterType<BackupMechanismA>().As<IFileBackup>().AsSelf();
builder.RegisterType<BackupMechanismB>().As<IFileBackUp>().AsSelf();
But this won't work because I still need to tell the caller which of the types to resolve. How do I do that in the caller?
Also, I'm in doubt whether this design is really the right design to go with. Before this design I just had one class with two different methods, one for mechanism A and one for mechanism B and then the caller would just call the different methods in the try catch. So I wanted to refactor this because the class got quite big and I wanted to separate the two different mechanisms into their own classes.
So, can I resolve this using Autofac? And is it the right design to go with for this scenario?
Agree with Jogge that iterating IFileBackups would be a better option, but creating an interface for each type is a no go. Instead, you could add a class which provides IEnumerable<IFileBackup> (an aggregate). For example:
public class BackupBundle : IEnumerable<IFileBackup>
{
private readonly List<IFileBackup> _backups = new List<IFileBackup>();
// default constructor creates default implementations
public BackupBundle()
: this(new List<IFileBackup> {new BackUpMechanismA(), new BackUpMechanismB()}) {}
// allow users to add custom backups
public BackupBundle(IEnumerable<IFileBackup> backups)
{
foreach (var backup in backups)
Add(backup);
}
public void Add(IFileBackup backup)
{
if (backup == null) throw new ArgumentNullException(nameof(backup));
_backups.Add(backup);
}
public IEnumerator<IFileBackup> GetEnumerator()
{
foreach (var backup in _backups)
yield return backup;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Caller
{
private readonly IEnumerable<IFileBackup> _backups;
public Caller(IEnumerable<IFileBackup> backups)
{
_backups = backups ?? throw new ArgumentNullException(nameof(backups));
}
public async Task BackupFile(byte[] file)
{
foreach (var b in _backups)
{
try
{
await b.Backup(file);
break;
}
catch (Exception e) { }
}
}
}
Registration can be done as follows:
builder.RegisterInstance(new BackupBundle()).As<IEnumerable<IFileBackup>>();
builder.RegisterType<Caller>();
which allows you to resolve by class name:
var caller = scope.Resolve<Caller>();
As you see, the BackupBundle has a dependency of BackUpMechanismA and BackUpMechanismB. You could get rid of it by introducing another layer of abstraction but I'd prefer not to do that. My main concern would be to make Caller more robust. You might want to introduce retry logic, timeouts, etc.
Try registering with a name and then resolve using the name:
builder.RegisterType<BackupMechanismA>().Named<IFileBackup>("BackUpMechanismA");
builder.RegisterType<BackupMechanismB>().Named<IFileBackUp>("BackUpMechanismB");
_backupA = container.ResolveNamed<IFileBackUp>
("BackUpMechanismA");
_backupB = container.ResolveNamed<IFileBackUp>
("BackUpMechanismB");
Resolve the instances during runtime, rather than injecting through the constructor. This will let you resolve to the respective type, as needed.
Let me know if this works.
To make your design work, you can try the next approach:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BackUpMechanismA>().Keyed<IFileBackup>("A");
builder.RegisterType<BackUpMechanismB>().Keyed<IFileBackup>("B");
builder.RegisterType<Caller>()
.WithParameter((p, ctx) => p.Position == 0, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("A"))
.WithParameter((p, ctx) => p.Position == 1, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("B"));
IContainer container = builder.Build();
var caller = container.Resolve<Caller>();
Console.ReadKey();
}
However in my opinion you probably don't need such a polymorphism here. It will be much more obvious and descriptive to implement something like this:
public async Task BackupFile(byte[] file)
{
try
{
await BackUpToAmazonS3(file);
}
catch (AmazonS3LoadingException)
{
await BackUpToLocalDisk(file);
}
}
In this example it is obvious what is going on. And there in BackUpToAmazonS3 you can use some injected AmazonS3FileBackUp and in BackUpToLocalDisk use LocalDiskFileBackUp or whatever. The point is that you don't need a polymorphism, when you don't plan to change the implementation. In your context it should be clear? that you try to put backup to some remote storage, and then, if it fails, put in on local disk. You don't need to hide the meaning here. This is your logic and should be clear, when you read the code, I suppose. Hope it helps.
In my experience, you're better off by creating an interface for each type:
public interface IFileBackup
{
Task Backup(byte[] file);
}
public interface IBackUpMechanismA : IFileBackup
{
}
public class BackUpMechanismA : IBackUpMechanismA
{
//...
}
public interface IBackUpMechanismB : IFileBackup
{
}
public class BackUpMechanismB : IBackUpMechanismB
{
//...
}
If you don't want that, what you could do is getting injected a list of IFileBackup and just iterate them. If you register BackUpMechanismA first it will be the first in the list. I'm not sure if this is guaranteed, you have to look it up.
public class Caller
{
private readonly ICollection<IFileBackup> _fileBackups;
public Caller(ICollection<IFileBackup> fileBackups)
{
_fileBackups = fileBackups;
}
public async Task BackupFile(byte[] file)
{
foreach (var fileBackup in _fileBackups)
{
try
{
await fileBackup.Backup(file);
break;
}
catch { }
}
}
}

Refactor long switch statement

I'm program in c# which you controlling by dictating command so now i have a long switch statement. Something like
switch (command)
{
case "Show commands":
ProgramCommans.ShowAllCommands();
break;
case "Close window":
ControlCommands.CloseWindow();
break;
case "Switch window":
ControlCommands.SwitchWindow();
break;
}
and so on
Almost all cases call only one method, methods are not in one class they are distributed in many classes. So the question is, how i could refactor this switch to more elegant way?
You can do this to refactor your switch statement:
var commands = new Dictionary<string, Action>()
{
{ "Show commands", () => ProgramCommans.ShowAllCommands() },
{ "Close window", () => ControlCommands.CloseWindow() },
{ "Switch window", () => ControlCommands.SwitchWindow() },
};
if (commands.ContainsKey(command))
{
commands[command].Invoke();
}
The main advantage to this approach is that you can change the "switch" at run-time.
I much prefer the Strategy Pattern for extending switch case statements. First, I create an interface that defines what each rule should look like:
public interface IWindowRule
{
string Command { get; }
void Invoke();
}
Then create a class that implements the interface for each possible case:
public class ShowAllWindowRule : IWindowRule
{
public string Command => "Show commands";
private ProgramCommands _progCommands;
public ShowAllWindowRule(ProgramCommands programCommands) =>
_progCommands = programCommands;
public void Invoke() => _progCommands.ShowAllCommands();
}
public class CloseWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Close window";
public CloseWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.CloseWindow();
}
public class SwitchWindowRule : IWindowRule
{
private ControlCommands _ctrlCommands;
public string Command => "Switch window";
public SwitchWindowRule(ControlCommands ctrlCommands) =>
_ctrlCommands = ctrlCommands;
public void Invoke() =>
_ctrlCommands.SwitchWindow();
}
Then your switch statement turns into this:
public void RunWindowRule(IList<IWindowRule> rules, string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
Now you can pass the function any set of rules you wish and run them making the function adhere to the Open/Closed principle.
I realize this may appear to be a bit of over engineering, and I do think there are more functional solutions that require a bit less work, however this has the added benefit of allowing you to extend this function by creating classes that inject the list of rules for a myriad of circumstances or even make a builder class that give you a fluent API.
public class WindowRuleBuilder
{
private IList<IWindowRule> rules;
public WindowRuleBuilder(IList<IWindowRule> rules = null) =>
rules = rules ?? new List<IWindowRule>();
public WindowRuleBuilder AddRule(IWindowRule newRule)
{
rules.Add(newRule);
return this;
}
public void Run(string command)
{
foreach (IWindowRule rule in rules)
{
if (rule.Command == command) rule.Invoke();
}
}
}
Now you have something like this:
public static void Main(string[] args)
{
WindowRuleBuilder ruleBuilder = new WindowRuleBuilder()
.AddRule(new CloseWindowRule(conrolCommands))
.AddRule(new ShowAllWindowRule(programCommands))
.AddRule(new SwitchWindowRule(controlCommands));
ruleBuilder.Run(args[0]);
}
This is highly extendable as for ever new rule you simply create the class and add it to the rule builder with the AddRule() method. It also doesn't take much reading to understand what's going on here. It's a much more compositional approach. Though I again admit, it does take a bit of work to implement but the code adheres to SOLID and is finely decoupled.
If all the functions get the same parameters and return the same value, you can use a Dictionary along with delegates to map a string to a function(s). This method will allow you also to change in run time the switch - allowing external programs to extend the functionality of the program.
If the functions aren't the same, you could write wrappers - a proxy function that will get parameters as all other functions, and call the functions you want.
I realize this is an old post, but in these situations I find attributes and a factory very handy.
The following code uses a custom attribute (Command) to allow you to attribute your methods, providing a string value of how they should respond to you.
The factory method uses reflection to generate a dictionary of these methods and calls it whenever you call CommandFactory.
Things could get cleaned up a bit, calling invoke is a little ugly, but it just depends on how you want to execute the code.
using System.Collections.Generic;
using System.Linq;
namespace MyApp
{
using System.Reflection;
using MyApp.Commands;
class Program
{
static void Main(string[] args)
{
var methods = new MyCommands();
MethodInfo myMethod;
myMethod = CommandFactory.GetCommandMethod("Show Commands");
myMethod.Invoke(methods, null);
myMethod = CommandFactory.GetCommandMethod("Close window");
myMethod.Invoke(methods, null);
myMethod = CommandFactory.GetCommandMethod("Switch window");
myMethod.Invoke(methods, null);
}
}
public static class CommandFactory
{
private static Dictionary<string, MethodInfo> speechMethods = new Dictionary<string, MethodInfo>();
public static MethodInfo GetCommandMethod(string commandText)
{
MethodInfo methodInfo;
var commands = new MyCommands();
if (speechMethods.Count == 0)
{
var methodNames =
typeof(MyCommands).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
var speechAttributeMethods = methodNames.Where(y => y.GetCustomAttributes().OfType<CommandAttribute>().Any());
foreach (var speechAttributeMethod in speechAttributeMethods)
{
foreach (var attribute in speechAttributeMethod.GetCustomAttributes(true))
{
speechMethods.Add(((CommandAttribute)attribute).Command, speechAttributeMethod);
}
}
methodInfo = speechMethods[commandText];
}
else
{
methodInfo = speechMethods[commandText];
}
return methodInfo;
}
}
}
namespace MyApp.Commands
{
class MyCommands
{
[Command("Show All")]
[Command("Show All Commands")]
[Command("Show commands")]
public void ShowAll()
{
ProgramCommands.ShowAllCommands();
}
[Command("Close Window")]
public void CloseWindow()
{
ControlCommands.CloseWindow();
}
[Command("Switch Window")]
public void SwitchWindow()
{
ControlCommands.SwitchWindow();
}
}
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = true)]
public class CommandAttribute : System.Attribute
{
public string Command
{
get;
set;
}
public CommandAttribute(string textValue)
{
this.Command = textValue;
}
}
}
I know the answer is a bit late, to not abuse the SOLID principle, you may use interface or inheritance. In this example, I use inheritance because u may have other usages of "command" string.
public abstract class commandRepository {
string command ; // if there is no usage in other function class, you can get rid of it
public abstract void DoCommands();
}
public class ShowCommands:commandRepository
{
public ShowCommands (){
command ="Show commands"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.ShowAllCommands();
}
}
public class CloseWindow:commandRepository
{
public CloseWindow (){
command ="Close window"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.CloseWindow();
}
}
public class SwitchWindow:commandRepository
{
public SwitchWindow (){
command ="Switch window"; // if there is no usage in other function class, you can get rid of it
}
public override void DoCommands(){
ProgramCommans.SwitchWindow();
}
}
Here's what you can do here. You can create an interface [ICommand] where you can place a common function [eg: Execute].
Then you just needs to initiate that member with appropriate type and call the Execute function. This might include more functions in the future and is thus extended.
Also, you can create a factory method where you can pass the parameter and get the appropriate class to work with.
Hope that helps.

Some design-pattern suggestions needed

C#. I have a base class called FileProcessor:
class FileProcessor {
public Path {get {return m_sPath;}}
public FileProcessor(string path)
{
m_sPath = path;
}
public virtual Process() {}
protected string m_sath;
}
Now I'd like to create to other classes ExcelProcessor & PDFProcessor:
class Excelprocessor: FileProcessor
{
public void ProcessFile()
{
//do different stuff from PDFProcessor
}
}
Same for PDFProcessor, a file is Excel if Path ends with ".xlsx" and pdf if it ends with ".pdf". I could have a ProcessingManager class:
class ProcessingManager
{
public void AddProcessJob(string path)
{
m_list.Add(Path;)
}
public ProcessingManager()
{
m_list = new BlockingQueue();
m_thread = new Thread(ThreadFunc);
m_thread.Start(this);
}
public static void ThreadFunc(var param) //this is a thread func
{
ProcessingManager _this = (ProcessingManager )var;
while(some_condition) {
string fPath= _this.m_list.Dequeue();
if(fPath.EndsWith(".pdf")) {
new PDFProcessor().Process();
}
if(fPath.EndsWith(".xlsx")) {
new ExcelProcessor().Process();
}
}
}
protected BlockingQueue m_list;
protected Thread m_thread;
}
I am trying to make this as modular as possible, let's suppose for example that I would like to add a ".doc" processing, I'd have to do a check inside the manager and implement another DOCProcessor.
How could I do this without the modification of ProcessingManager? and I really don't know if my manager is ok enough, please tell me all your suggestions on this.
I'm not really aware of your problem but I'll try to give it a shot.
You could be using the Factory pattern.
class FileProcessorFactory {
public FileProcessor getFileProcessor(string extension){
switch (extension){
case ".pdf":
return new PdfFileProcessor();
case ".xls":
return new ExcelFileProcessor();
}
}
}
class IFileProcessor{
public Object processFile(Stream inputFile);
}
class PdfFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
class ExcelFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
This should make sure you are using the FileProcessorFactory to get the correct processor, and the IFileProcessor will make sure you're not implementing different things for each processor.
and implement another DOCProcessor
Just add a new case to the FileProcessorFactory, and a new class which implements the interface IFileProcessor called DocFileProcessor.
You could decorate your processors with custom attributes like this:
[FileProcessorExtension(".doc")]
public class DocProcessor()
{
}
Then your processing manager could find the processor whose FileProcessorExtension property matches your extension, and instantiate it reflexively.
I agree with Highmastdon, his factory is a good solution. The core idea is not to have any FileProcessor implementation reference in your ProcessingManager anymore, only a reference to IFileProcessor interface, thus ProcessingManager does not know which type of file it deals with, it just knows it is an IFileProcessor which implements processFile(Stream inputFile).
In the long run, you'll just have to write new FileProcessor implementations, and voila. ProcessingManager does not change over time.
Use one more method called CanHandle for example:
abstract class FileProcessor
{
public FileProcessor()
{
}
public abstract Process(string path);
public abstract bool CanHandle(string path);
}
With excel file, you can implement CanHandle as below:
class Excelprocessor: FileProcessor
{
public override void Process(string path)
{
}
public override bool CanHandle(string path)
{
return path.EndsWith(".xlsx");
}
}
In ProcessingManager, you need a list of processor which you can add in runtime by method RegisterProcessor:
class ProcessingManager
{
private List<FileProcessor> _processors;
public void RegisterProcessor(FileProcessor processor)
{
_processors.Add(processor)
}
....
So LINQ can be used in here to find appropriate processor:
while(some_condition)
{
string fPath= _this.m_list.Dequeue();
var proccessor = _processors.SingleOrDefault(p => p.CanHandle(fPath));
if (proccessor != null)
proccessor.Process(proccessor);
}
If you want to add more processor, just define and add it into ProcessingManager by using
RegisterProcessor method. You also don't change any code from other classes even FileProcessorFactory like #Highmastdon's answer.
You could use the Factory pattern (a good choice)
In Factory pattern there is the possibility not to change the existing code (Follow SOLID Principle).
In future if a new Doc file support is to be added, you could use the concept of Dictionaries. (instead of modifying the switch statement)
//Some Abstract Code to get you started (Its 2 am... not a good time to give a working code)
1. Define a new dictionary with {FileType, IFileProcessor)
2. Add to the dictionary the available classes.
3. Tomorrow if you come across a new requirement simply do this.
Dictionary.Add(FileType.Docx, new DocFileProcessor());
4. Tryparse an enum for a userinput value.
5. Get the enum instance and then get that object that does your work!
Otherwise an option: It is better to go with MEF (Managed Extensibility Framework!)
That way, you dynamically discover the classes.
For example if the support for .doc needs to be implemented you could use something like below:
Export[typeof(IFileProcessor)]
class DocFileProcessor : IFileProcessor
{
DocFileProcessor(FileType type);
/// Implement the functionality if Document type is .docx in processFile() here
}
Advantages of this method:
Your DocFileProcessor class is identified automatically since it implements IFileProcessor
Application is always Extensible. (You do an importOnce of all parts, get the matching parts and Execute.. Its that simple!)

Categories