Looking for design guidelines for the following problem.
I'm receiving two string values - action and message and have to call appropriate method which processes string message (processM1MessageVer1, processM1MessageVer2, processM2MessageVer1...). The method I have to call depends on the given string action. There are 2 versions (but in future there might be more) of each processing method. The version of method I have to call is determined by global variable version. Every method returns object of different type (ResultObject1, ResultObject2...). The result has to be serialized, converted to base64 and returned back.
Is there more elegant way of writing this (eliminate duplicate code, make possible future changes easier, reduce code...):
string usingVersion = "ver1";
public string processRequest(string action, string message)
if (usingVersion == "ver1"){
processRequestVer1(action, message);
}
else{
processRequestVer2(action, message);
}
}
//version 1
public string processRequestVer1(string action, string message){
string result = "";
switch (action){
case "m1":
ResultObject1 ro = processM1MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
case "m2":
ResultObject2 ro = processM2MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
case "m3":
ResultObject3 ro = processM3MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
}
return result;
}
//version 2
public string processRequestVer2(string action, string message){
string result = "";
switch (action){
case "m1":
ResultObject1 ro = processM1MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
case "m2":
ResultObject2 ro = processM2MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
case "m3":
ResultObject3 ro = processM3MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
}
return result;
}
It would be simplier if messages that have to be processed are of different object types instead of strings so that appropriate method could be called polymorphically. The fact that every process method returns different object type also complicates things even more. But these don't depend on me and I cannot change it.
My approach (make it more object oriented, and you should justify whether it's appropriate to create class structure depending on how complex your processing logic is. If your processing logic is only little then maybe this is over-engineering):
For serialize and convert to base 64, I assume you have some logic to do those tasks in a generic way. If not, move those to sub class also
public interface IRequestProcessorFactory
{
IRequestProcessor GetProcessor(string action);
}
public class FactoryVersion1 : IRequestProcessorFactory
{
public IRequestProcessor GetProcessor(string action)
{
switch(action)
{
case "m1":
return new M1Ver1RequestProcessor();
case "m2":
return new M2Ver1RequestProcessor();
case "m3":
return new M3Ver1RequestProcessor();
default:
throw new NotSupportedException();
}
}
}
public class FactoryVersion2 : IRequestProcessorFactory
{
public IRequestProcessor GetProcessor(string action)
{
switch(action)
{
case "m1":
return new M1Ver2RequestProcessor();
case "m2":
return new M2Ver2RequestProcessor();
case "m3":
return new M3Ver2RequestProcessor();
default:
throw new NotSupportedException();
}
}
}
public interface IRequestProcessor
{
string ProcessRequest(string message);
}
public class RequestProcessorBase<T>
{
public string ProcessRequest(string message)
{
T result = Process(message);
string serializedResult = Serialize(result);
return ConvertToB64(serializedResult);
}
protected abstract T Process(string message);
private string Serialize(T result)
{
//Serialize
}
private string ConvertToB64(string serializedResult)
{
//Convert
}
}
public class M1Ver1RequestProcessor : RequestProcessorBase<ResultObject1>
{
protected ResultObject1 Process(string message)
{
//processing
}
}
public class M2Ver1RequestProcessor : RequestProcessorBase<ResultObject2>
{
protected ResultObject2 Process(string message)
{
//processing
}
}
public class M3Ver1RequestProcessor : RequestProcessorBase<ResultObject3>
{
protected ResultObject3 Process(string message)
{
//processing
}
}
public class M1Ver2RequestProcessor : RequestProcessorBase<ResultObject1>
{
protected ResultObject1 Process(string message)
{
//processing
}
}
public class M2Ver2RequestProcessor : RequestProcessorBase<ResultObject2>
{
protected ResultObject2 Process(string message)
{
//processing
}
}
public class M3Ver2RequestProcessor : RequestProcessorBase<ResultObject3>
{
protected ResultObject3 Process(string message)
{
//processing
}
}
Usage:
string action = "...";
string message = "...";
IRequestProcessorFactory factory = new FactoryVersion1();
IRequestProcessor processor = factory.GetProcessor(action);
string result = processor.ProcessRequest(message);
The switch is still there in factory class, but it only returns processor and doesn't do actual work so it's fine for me
First - define interface that suit you best, like this
public interface IProcessMessage
{
string ActionVersion { get; }
string AlgorithmVersion { get; }
string ProcessMessage(string message);
}
Then create as many implementation as you need
public class processorM1Ver1 : IProcessMessage
{
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM1MessageVer1(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
public string ActionVersion {get { return "m1"; }}
public string AlgorithmVersion {get { return "ver1"; }}
}
public class processorM2Ver1 : IProcessMessage
{
public string ActionVersion {get { return "m2"; }}
public string AlgorithmVersion {get { return "ver1"; }}
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM2MessageVer1(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
}
public class processorM1Ver2 : IProcessMessage
{
public string ActionVersion {get { return "m1"; }}
public string AlgorithmVersion {get { return "ver2"; }}
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM1MessageVer2(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
}
Now you need something that know which implementation is best in current context
public class MessageProcessorFactory
{
private MessageProcessorFactory() { }
private static readonly MessageProcessorFactory _instance = new MessageProcessorFactory();
public static MessageProcessorFactory Instance { get { return _instance; }}
private IEnumerable<IProcessMessage> _processorCollection;
IEnumerable<IProcessMessage> ProcessorCollection
{
get
{
if (_processorCollection == null)
{
//use reflection to find all imlementation of IProcessMessage
//or initialize it manualy
_processorCollection = new List<IProcessMessage>()
{
new processorM1Ver1(),
new processorM2Ver1(),
new processorM1Ver2()
};
}
return _processorCollection;
}
}
internal IProcessMessage GetProcessor(string action)
{
var algorithVersion = ReadAlgorithVersion();
var processor = ProcessorCollection.FirstOrDefault(x => x.AlgorithmVersion == algorithVersion && x.ActionVersion == action);
return processor;
}
private string ReadAlgorithVersion()
{
//read from config file
//or from database
//or where this info it is kept
return "ver1";
}
}
It can be use in such way
public class Client
{
public string ProcessRequest(string action, string message)
{
IProcessMessage processor = MessageProcessorFactory.Instance.GetProcessor(action);
return processor.ProcessMessage(message);
}
}
Related
I have created an interface that in theory should be able to return multiple generic lists of different types to provide the client with various information. When I attempt to loop through the results of the list it is only able to return first collection, can you help me to understand how I should be returning results from the following:
Interface class:
public interface IExampleInterface{}
public class ExampleType : IExampleInterface
{
public int First;
public int Last;
}
public class ExampleAmount : IExampleInterface
{
public decimal Amount;
public decimal TotalFee;
}
public class ExampleFacts : IExampleInterface
{
public bool TooLow;
public bool TooHigh;
}
Interface provider:
public class ExampleInterfaceProvider
{
private static readonly string conn = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
public static List<IExampleInterface> ExampleResults(int id)
{
//declare variables, read from database query using ExecuteReader...
var sT = new ExampleType
{
First = first;
Last = last;
}
var sA = new ExampleAmount
{
Amount = amount;
TotalFee = totalFee;
}
var sF = new ExampleFacts
{
TooHigh = tooHigh;
TooLow = tooLow;
}
var exampleResults = new List<IExampleInterface> {sT, sA, sF};
return exampleResults;
}
}
On the page I need to return the data:
foreach (dynamic item in ExampleResults(0))
{
Response.Write(item.First.ToString())
Response.Write(item.Last.ToString())
//The first two for 'sT' read fine, it breaks here
Response.Write(item.Amount.ToString())
//... And so on
}
Any help would be much appreciated,
Thanks
I think, there is no another solution except comparing implementations;
foreach (IExampleInterface item in ExampleResults(0))
{
if (item is ExampleType)
{
var exampleType = (ExampleType)item;
Response.Write(exampleType.First.ToString())
Response.Write(exampleType.Last.ToString())
}
else if (item is ExampleAmount)
{
var exampleAmount = (ExampleAmount)item;
Response.Write(exampleAmount.Amount.ToString())
}
//... And so on
}
If you are using C# 7, you can perform it as switch case
foreach (IExampleInterface item in ExampleResults(0))
{
switch (item)
{
case ExampleType c:
Response.Write(c.First.ToString());
Response.Write(c.Last.ToString());
break;
case ExampleAmount c:
Response.Write(c.Amount.ToString());
break;
default:
break;
}
//... And so on
}
You can find the documentation.
So basically, the items implementing IExampleInterface should all be written to a Response in a way that is somewhat specific to the actual type implementing the interface?
Then how about this:
public interface IExampleInterface
{
void WriteTo(Response response);
}
public class ExampleType : IExampleInterface
{
public int First;
public int Last;
public void WriteTo(Response response)
{
response.Write(First.ToString());
response.Write(Last.ToString());
}
}
public class ExampleAmount : IExampleInterface
{
public decimal Amount;
public decimal TotalFee;
public void WriteTo(Response response)
{
response.Write(Amount.ToString());
response.Write(TotalFee.ToString());
}
}
public class ExampleFacts : IExampleInterface
{
public bool TooLow;
public bool TooHigh;
public void WriteTo(Response response)
{
response.Write(TooLow.ToString());
response.Write(TooHigh.ToString());
}
}
And then:
foreach (IExampleInterface item in ExampleResults(0))
{
item.WriteTo(Response);
}
Assuming that Response is a variable holding an instance of the response rather than a static class.
I have a WPF C# application.
I need it to be able to save 'Products'. These products will have a Product name, Customer name, and firmware location. This is my current code for saving and loading however it is not working. I'm thinking of trying a different approach to it all together:
public class Product
{
private string productName;
private string customerName;
private string firmwareLocation;
public string getProductName()
{
return productName;
}
public bool setProductName(string inputProductName)
{
productName = inputProductName;
return true;
}
public string getCustomerName()
{
return customerName;
}
public bool setCustomerName(string inputCustomerName)
{
customerName = inputCustomerName;
return true;
}
public string getFirmwareLocation()
{
return firmwareLocation;
}
public bool setFirmwareLocation(string inputFirmwareLocation)
{
inputFirmwareLocation = firmwareLocation;
return true;
}
public Product(string inProductName, string inCustomerName, string inFirmwareLocation)
{
inProductName = productName;
inCustomerName = customerName;
inFirmwareLocation = firmwareLocation;
}
public void Save(TextWriter textOut)
{
textOut.WriteLineAsync(productName);
textOut.WriteLineAsync(customerName);
textOut.WriteLineAsync(firmwareLocation);
}
public bool Save(string filename)
{
TextWriter textOut = null;
try
{
textOut = new StreamWriter(filename);
Save(textOut);
}
catch
{
return false;
}
finally
{
if (textOut != null)
{
textOut.Close();
}
}
return true;
}
public static Product Load (string filename)
{
Product result = null;
System.IO.TextReader textIn = null;
try
{
textIn = new System.IO.StreamReader(filename);
string productNameText = textIn.ReadLine();
string customerNameText = textIn.ReadLine();
string firmwareLocationText = textIn.ReadLine();
result = new Product(productNameText, customerNameText, firmwareLocationText);
}
catch
{
return null;
}
finally
{
if (textIn != null) textIn.Close();
}
return result;
}
}
}
It's a little unclear what you mean by "not working" but I'd suggest that you just use the standard .NET serialization/deserialization libraries for this rather than trying to reinvent the wheel. There's no need to do anything custom here. See the following: https://msdn.microsoft.com/en-us/library/mt656716.aspx
As a side note, why are you using getX() and setX() methods instead of properties? It's not standard C#. For example, the following:
private string productName;
public string getProductName()
{
return productName;
}
public bool setProductName(string inputProductName)
{
productName = inputProductName;
return true;
}
should be
public string ProductName
{
get;
set;
}
I'm guessing that one of the reasons your code isn't working is that it has multiple glaring race conditions. For example, all 3 of your writes are asynchronous and fired off right after the other; there's no guarantee that the previous one will be done when you start the next one. It's not even clear to me that you're guaranteed to write the lines in a particular order (which you're counting to be the case in your deserialization logic). It's also completely possible (likely, actually) that you'll close the file in the middle of your write operations.
I'd also suggest a "using" block for the file streams.
I am trying to find the right design pattern for the below scenario.
I have a dataaccess class that can access different datasource. So I have designed to have an implementation class for each datasource(DataAccessMongo, DataAccesssql).
Based on the configuration change the data source must be switched. I believe the right way to do this is to use dependency injection and the data access class that have must accept an interface as a dependency. In the below scenario all the methods are static and I am unable to have a static method in an interface. So for now I am using a enum to check what is the data access type and call the corresponding method. If there are more data sources then definitely I should add more conditions for each data source. I would like a to arrive at a better design pattern. Please suggest what will be the best patter for this scenario. Thanks.
//Implementation class for Mongo
Public Class DataAccessMongo
{
public static string FindById(string itemId)
{
...
}
public static string FindByName(string itemId)
{
...
}
public static string FindByLastName(string itemId)
{
...
}
}
//Implementation class for Sql
Public Class DataAccessSql
{
public static string FindById(string itemId)
{
...
}
public static string FindByName(string itemId)
{
...
}
public static string FindByLastName(string itemId)
{
...
}
}
Public Class DataAccess
{
public static string FindById(string id)
{
string result = string.Empty;
if (databaseType == EnumDb.Mongo)
{
result = DataAccessMongo.FindById(id);
}
else if (databaseType == EnumDb.Sql){
result = DataAccessSql.FindById(id);
}
return result;
}
public static string FindByName(string itemId)
{
string result = string.Empty;
if (databaseType == EnumDb.Mongo)
{
result = DataAccessMongo.FindByName(id);
}
else if (databaseType == EnumDb.Sql){
result = DataAccessSql.FindByName(id);
}
return result;
}
public static string FindByLastName(string itemId)
{
string result = string.Empty;
if (databaseType == EnumDb.Mongo)
{
result = DataAccessMongo.FindByLastName(id);
}
else if (databaseType == EnumDb.Sql){
result = DataAccessSql.FindByLastName(id);
}
return result;
}
}
Note: These methods serve the web API methods.
This contrived example is roughly how my code is structured:
public abstract class SuperHeroBase
{
protected SuperHeroBase() { }
public async Task<CrimeFightingResult> FightCrimeAsync()
{
var result = new CrimeFightingResult();
result.State = CrimeFightingStates.Fighting;
try
{
await FightCrimeOverride(results);
}
catch
{
SetError(results);
}
if (result.State == CrimeFightingStates.Fighting)
result.State = CrimeFightingStates.GoodGuyWon;
return result;
}
protected SetError(CrimeFightingResult results)
{
result.State = CrimeFightingStates.BadGuyWon;
}
protected abstract Task FightCrimeOverride(CrimeFightingResult results);
}
public enum CrimeFightingStates
{
NotStarted,
Fighting,
GoodGuyWon, // success state
BadGuyWon // error state
}
public class CrimeFightingResult
{
internal class CrimeFightingResult() { }
public CrimeFightingStates State { get; internal set; }
}
Now I'm trying to build a collection that would hold multiple SuperHero objects and offer a AllHerosFightCrime method. The hero's should not all fight at once (the next one starts when the first is finished).
public class SuperHeroCollection : ObservableCollection<SuperHeroBase>
{
public SuperHeroCollection() { }
// I mark the method async...
public async IObservable<CrimeFightingResult> AllHerosFightCrime()
{
var heros = new List<SuperHeroBase>(this);
var results = new ReplaySubject<CrimeFightingResult>();
foreach (var hero in heros)
{
// ... so I can await on FightCrimeAsync and push
// the result to the subject when done
var result = await hero.FightCrimeAsync();
results.OnNext(result);
}
results.OnCompleted();
// I can't return the IObservable here because the method is marked Async.
// It expects a return type of CrimeFightingResult
return results;
}
}
How can I return the IObservable<CrimeFightingResults> and still have the call to FightCrimeAsync awaited?
You could turn your task into an observable and combine them using Merge:
public IObservable<CrimeFightingResult> AllHerosFightCrime()
{
var heros = new List<SuperHeroBase>(this);
return heros.Select(h => h.FightCrimeAsync().ToObservable())
.Merge();
}
If you want to maintain the order your events are received you can use Concat instead of Merge.
In my project I have a generic Packet class. I would like to be able to upcast to other classes (like LoginPacket or MovePacket).
The base class contains a command and arguments (greatly simplified):
public class Packet
{
public String Command;
public String[] Arguments;
}
I would like to have be able to convert from Packet to LoginPacket (or any other) based on a check if Packet.Command == "LOGIN". The login packet would not contain any new data members, but only methods for accessing specific arguments. For example:
public class LoginPacket : Packet
{
public String Username
{
get { return Arguments[0]; }
set { Arguments[0] == value; }
}
public String Password
{
get { return Arguments[1]; }
set { Arguments[1] == value; }
}
}
It would be great if I could run a simple code that would cast from Packet to LoginPacket with something like LoginPacket _Login = (LoginPacket)_Packet;, but that throws a System.InvalidCastException.
It seems like this would be an easy task, as no new data is included, but I can't figure out any other way than copying everything from the Packet class to a new LoginPacket class.
A better approach is to make Packet instance encapsulated by LoginPacket.
This will allow you to do:
LoginPacket _Login = new LoginPacket(_packet);
Also consider creating a PacketFactory where all the logic needed to create various Packet's goes in.
public class Packet
{
public String Command;
public String[] Arguments;
}
public abstract class AbstractPacket
{
private Packet _packet;
public AbstractPacket(Packet packet)
{
_packet = packet;
}
public string this[int index]
{
get { return _packet.Arguments[index]; }
set { _packet.Arguments[index] = value; }
}
}
public class LoginPacket : AbstractPacket
{
public LoginPacket(Packet packet): base(packet)
{
}
public string Username
{
get { return base[0]; }
set { base[0] = value; }
}
public string Password
{
get { return base[1]; }
set { base[1] = value; }
}
}
If different type of Packets differ only by available data members then you could do something below:
Use PacketGenerator to generate packets as:
Packet packet = PacketGenerator.GetInstance(packetdata);
Access the properties as:
Console.WriteLine("User Name: {0}", packet["UserName"]);
Code..
public enum PacketType { Undefined, LoginPacket, MovePacket }
public class PacketData
{
public String Command;
public String[] Arguments;
}
public class Packet
{
public readonly PacketType TypeOfPacket;
private Dictionary<string, string> _argumentMap;
public Packet(PacketType _packetType,
Dictionary<string, string> argumentMap)
{
TypeOfPacket = _packetType;
_argumentMap = argumentMap;
}
public string this[string index]
{
get { return _argumentMap[index]; }
set { _argumentMap[index] = value; }
}
}
public static class PacketFactory
{
Packet GetInstance(PacketData packetData)
{
Dictionary<string, string> argumentMap
= new Dictionary<string, string>();
PacketType typeOfPacket = PacketType.Undefined;
// Replace inline strings/int with static/int string definitions
switch (packetData.Command.ToUpper())
{
case "LOGIN":
typeOfPacket = PacketType.LoginPacket;
argumentMap["UserName"] = packetData.Arguments[0];
argumentMap["PassWord"] = packetData.Arguments[1];
break;
case "MOVE":
typeOfPacket = PacketType.MovePacket;
//..
break;
default:
throw new ArgumentException("Not a valid packet type");
}
return new Packet(typeOfPacket, argumentMap);
}
}