I have created a solution to read/process various kinds of files, e.g. XML, JSON, txt.
public interface IFileProcessor
{
TOutput Process<TInput, TOutput>(TInput input);
}
public abstract class FileProcessorBase
{
protected readonly FileInfo fileInfo;
protected FileProcessorBase(FileInfo fileInfo)
{
this.fileInfo = fileInfo;
}
protected abstract TOutput Load<TOutput>();
}
And the concrete class as follows.
public class JsonFileProcessor : FileProcessorBase, IFileProcessor
{
public JsonFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
//Call Load Method
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
protected override TOutput Load<TOutput>()
{
string res = "JSON Load method";
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
}
Concrete class for XML
public class XMLFileProcessor : FileProcessorBase, IFileProcessor
{
public XMLFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput));
}
protected override TOutput Load<TOutput>()
{
string xml = "XML";
return (TOutput)Convert.ChangeType(xml, typeof(TOutput));
}
}
and now this is factory class
public class FileProcessorFactory
{
static readonly Dictionary<string, IFileProcessor> fileProcessor;
static FileProcessorFactory()
{
fileProcessor = new Dictionary<string, IFileProcessor>();
fileProcessor.Add("XML", new XMLFileProcessor(new FileInfo(""));
fileProcessor.Add("JSON", new JsonFileProcessor(new FileInfo(""));
}
public static IFileProcessor GetFileProcessor(string key)
{
return fileProcessor[key];
}
}
Below is FileProcessorService class
public class FileProcessorService
{
IFileProcessor fileProcessor;
public FileProcessorService(IFileProcessor fileProcessor)
{
this.fileProcessor = fileProcessor;
}
public TOutput Process<TInput, TOutput>(TInput from)
{
return fileProcessor.Process<TInput, TOutput>(from);
}
}
Now Finally, I'm calling through this way.
IFileProcessor fileProcessor = FileProcessorFactory.GetFileProcessor("XML");
FileProcessorService fileProcessorService = new FileProcessorService(fileProcessor);
var XMLResult = fileProcessorService.Process<string, string>("");
Can I use base class in strategy pattern, If not what would be proposed solution.
This may help answer your specific question with regards whether their are any hard rules to say that the strategy pattern should not inherit any base implementation.
Can i use inheritance instead of implement an interface in strategy pattern?
In terms of your code have you considered passing an interface that has a method to return the stream of data, as opposed to using concrete FileInfo - as you could then remove base class entirely.
Here is my generic method from which i want to return the class object
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Above method calling the below static generic class which will handle object creation of a particular class
public static class PageObjectBase<T> where T : class, new()
{
private static T singleTonObject;
public static T PageObject
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if (singleTonObject == null)
{
singleTonObject = new T();
}
return singleTonObject;
}
}
How can i call the PageObject property from my test base class please advice.
Note : I have searched forum and find answers relevant to generic method to another generic method calling.The same is achieved by reflection.Can we use reflection in my case too? If so how can we do it.
You can add another constraint 'class' to NavigateandReturntheObject
public T NavigateandReturntheObject<T>() where T : class,new()
Complete Code.
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : class,new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Demo Code
public class TestClass
{
public string Name{get;set;}
public TestClass()
{
Name = "Dummy Name";
}
}
var testBase = new TestBase();
var sample = testBase.NavigateandReturntheObject<TestClass>();
Console.WriteLine(sample.Name);
Output
Dummy Name
I have about 20 classes which are derived from ConvertApi classes. Every class share Convert method from parent class and has unique property SupportedFiles. I use these classes for file manipulation and my code looks like
if (fileEx=="txt")
new Text2Pdf().Convert(file)
else
if (fileEx=="doc")
new Word2Pdf().Convert(file)
else
//and so on..
I know that these code can be optimized because 20 times if operator is repeated and that looks bad, but can't find a way to do that. Could anyone help me?
class Text2Pdf : ConvertApi
{
enum SupportedFiles { txt, log };
}
class Word2Pdf : ConvertApi
{
enum SupportedFiles { doc, docx };
}
class Excel2Pdf : ConvertApi
{
enum SupportedFiles { xls, xlsx };
}
class ConvertApi
{
public void Convert(....);
}
In your base class, have something like this:
public abstract class ConvertApi
{
protected abstract string[] SupportedFilesImpl();
public bool Supports(string ext)
{
return SupportedFilesImpl.Contains(ext);
}
}
Now, your derived classes can implement this method:
public class Text2PDF : ConvertApi
{
protected override string[] SupportedFilesImpl { return new string[] { "txt", "log"}; }
}
public class Doc2PDF : ConvertApi
{
protected override string[] SupportedFilesImpl { return new string[] { "doc", "docx"}; }
}
... and so on for the rest of the converters. Then put these in a list...
List<ConvertApi> converters = new List<ConvertApi>();
converters.Add(new Text2PDF());
converters.Add(new Doc2PDF());
(Note, I'd probably have a class containing these rather than just a list, but anyway). Now, to find a converter:
foreach(ConvertApi api in converters)
{
if(api.Supports(fileExt))
{
// woo!
break;
}
}
Assuming each converter is stateless, it sounds like you just want a Dictionary<string, ConvertApi>:
private static readonly Dictionary<string, ConvertApi> ConverterByType =
new Dictionary<string, ConvertApi>
{
{ "txt", new Text2PdfConverter() },
{ "doc", new Word2PdfConverter() },
...
};
...
ConvertApi converter;
if (!ConverterByType.TryGetValue(fileEx, out converter))
{
// No converter available... do whatever
}
else
{
converter.Convert(file);
}
(The dictionary initialization will end up creating more converters than you really need for any converter that supports multiple extensions, but that's a different matter.)
If you need a new converter each time, make it a Dictionary<string, Func<ConvertApi>> and populate it as:
{ "txt", () => new Text2PdfConverter() },
{ "doc", () => new Word2PdfConverter() },
... then call the delegate to get the converter when you need it.
Of course, this puts all the initialization in one place - you may want a way of getting the converters to register the extensions they understand with a "converter provider" of some type.
C# supports switch-case operator for strings, i.e. your code coud be rewritten as
switch (fileEx)
{
case "txt" : new Text2Pdf().Convert(file); break;
case "doc": new Word2Pdf().Convert(file); break;
...
}
If you change your classes' names to correspond to supported extensions then you will be able to construct them using reflection, like this (error checking omitted for brevity):
var t = Type.GetType(fileEx + "2Pdf");
var tConstructor = t.GetConstructor(Type.EmptyTypes);
var tInstance = tConstructor.Invoke(new object[0]);
((ConvertApi)tInstance).Convert(...);
This might require some additional work (i.e. create a separate class for each extension, deriving them from some base class - for example Doc2Pdf and Docx2Pdf both deriving from Word2Pdf).
The advantage is that you will not have to touch this part of code anymore. If you're planning to write some interface for plugins then it may come in handy.
The code above also has an assumption that your ConvertApi classes all have default parameterless constuctor.
You need to use an abstract factory pattern, here. All your text converters should derive from a common interface ITextConverter implementing your Convert method. The file extension would be a parameter of your factory. Here is a sample below (typed "on the fly", sometimes copy-pasting code from my sources, so there might be typos. The goal here is to give you a general idea for a flexible implementation).
public interface IFileConverter
{
bool Convert(string filePath);
}
public static class FileConverterFactory
{
public static IFileConverter Create(string extension)
{
extension = type.ToUpper();
Dictionary<string, ConverterConfig> availableConverters = GetConvertersConfig();
if (!availableConverters.ContainsKey(extension))
throw new ArgumentException(string.Format("Unknown extenstion type '{0}'. Check application configuration file.", extension));
ConverterConfig cc = availableConverters[extension];
Assembly runnerAssembly = Assembly.LoadFrom(cc.Assembly);
Type converterType = runnerAssembly.GetType(cc.Class);
IFileConverter converter = (IFileConverter) Activator.CreateInstance(converterType);
return converter;
}
private static Dictionary<string, ConverterConfig> GetConvertersConfig()
{
var configs = (Dictionary<string, ConverterConfig>) ConfigurationManager.GetSection("ConvertersConfig");
return configs;
}
}
public class ConvertersConfigHandler : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section)
{
Dictionary<string, ConverterConfig> converters = new KeyedList<string, ConverterConfig>();
XmlNodeList converterList = section.SelectNodes("Converter");
foreach (XmlNode converterNode in converterList)
{
XmlNode currentConverterNode = converterNode;
ConverterConfig cc = new ConverterConfig();
cc.Type = XML.GetAttribute(ref currentConverterNode, "Type").ToUpper();
cc.Assembly = XML.GetAttribute(ref currentConverterNode, "Assembly");
cc.Class = XML.GetAttribute(ref currentConverterNode, "Class");
converters[cc.Type] = cc;
}
return converters;
}
}
public class ConverterConfig
{
public string Type = "";
public string Assembly = "";
public string Class = "";
}
public class TextConverter : IFileConverter
{
bool Convert(string filePath) { ... }
}
public class PdfConverter : IFileConverter
{
bool Convert(string filePath) { ... }
}
In your app.config file, you add this to the configSections:
<section name = "ConvertersConfig" type = "ConvertersConfigConfigHandler, MyAssembly" />
and this below your configSections:
<ConvertersConfig>
<Converter Type="txt" Assembly="MyAssembly" Class="MyAssembly.TextConverter" />
<Converter Type="pdf" Assembly="MyAssembly" Class="MyAssembly.PdfConverter" />
</ConvertersConfig>
The call would then be like this:
IFileConverter converter = FileConverterFactory.Create("txt");
converter.Convert("c:\temp\myfile");
EDITED the code for giving a solution that is more "generic".
You can use some reflection:
ConvertApi FindMatchingConverter(string _FileExt)
{
//Get all the converters available.
List<ConvertApi> converters = this.GetType()
.Assembly
.GetExportedTypes()
.Where(type => type.IsAssignableFrom(typeof(ConvertApi)))
.ToList();
//Loop and find which converter to use
foreach (var converter in converters)
{
if (converter.SupportedFiles.Contains(_FileExt))
return Activator.CreateInstance(converter);
}
throw new Exception("No converter found");
}
Then you just have to call Convert() on the ConvertApi returned.
Of course, this requires you to add a virtual List<String> named SupportedFiles in your base class.
This makes it look like
public abstract class ConvertApi
{
public abstract void Convert();
public virtual List<String> SupportedFiles {get;set;}
}
What about using a switch?
switch(fileEx){
case "txt": new Text2Pdf().Convert(file); break;
case "doc": new Word2Pdf().Convert(file); break;
}
Use dependency injection where you pass in the supported files in the constructor of the class.
Slower, but more dynamic... use an Object Factory. Here's a good article that seems to fit your needs.
http://www.codeproject.com/Articles/12986/Generic-Object-Factory
The important stuff from the article:
using System.Collections.Generic;
public struct Factory < KeyType, GeneralProduct >
{
//Register a object with the factory
public void> Register< SpecificProduct >(KeyType key)
where SpecificProduct : GeneralProduct, new()
{
if( m_mapProducts == null )
{
m_mapProducts = new SortedList< KeyType, CreateFunctor >();
}
CreateFunctor createFunctor = Creator<SpecificProduct>;
m_mapProducts.Add(key, createFunctor);
}
//Create a registered object
public GeneralProduct Create( KeyType key )
{
CreateFunctor createFunctor = m_mapProducts[ key ];
return createFunctor();
}
private GeneralProduct Creator < SpecificProduct >()
where SpecificProduct : GeneralProduct, new()
{
return new SpecificProduct();
}
private delegate GeneralProduct CreateFunctor();
private SortedList<KeyType, CreateFunctor> m_mapProducts;
}
Usage:
class Fruit
{
}
class Apple : Fruit
{
}
class Orange : Fruit
{
}
class TestClass
{
static void Main(string[] args)
{
General.Factory< string, Fruit > factory;
//Register
factory.Register< Apple >( "Apple" );
factory.Register< Orange>( "Orange" );
//Create
Fruit fruit1 = factory.Create("Apple");
Fruit fruit2 = factory.Create("Orange");
}
}
I have the following:
List<IReport> myList = new List<IReport>();
Report myReport = TheirApi.GetReport();
myReport meets all the qualifications of IReport, but cannot implement IReport because I do not have access to the source of TheirApi. Casting to type IReport obviously results in null, and I read that I cannot cast an anonymous type to an interface.
Do I have any options here?
A wrapper class was just what the doctor ordered:
ReportServices.GetAllCustomReports().ToList().ForEach(customReport => _customReports.Add(new ReportWrapper(customReport)));
public class ReportWrapper : IReport
{
private Report inner;
public int ID
{
get { return inner.ID; }
set { inner.ID = value; }
}
public string Name
{
get { return inner.Name; }
set { inner.Name = value; }
}
public ReportWrapper(Report obj)
{
inner = obj;
}
}
You will need to wrap this object inside another one that implements the interface, and then you will need to implement it calling the inner object's properties and methods.
For example:
public class ReportWrapper : IReport
{
MyObjectIsLikeReport inner;
public ReportWrapper(MyObjectIsLikeReport obj) {
this.inner = obj;
}
public void ReportMethod(int value) {
this.inner.ReportMethod(value);
}
public int SomeProperty {
get { return this.inner.SomeProperty; }
set { this.inner.SomeProperty = value; }
}
}
To use it, you can do this:
List<IReport> myList = new List<IReport>();
MyObjectIsLikeReport myReport = TheirApi.GetReport();
myList.Add(new ReportWrapper(myReport));
Consider Adapter Design Pattern.
Definition: Convert the interface of a class into another interface
clients expect. Adapter lets classes work together that couldn't
otherwise because of incompatible interfaces.
good reference: http://www.dofactory.com/Patterns/PatternAdapter.aspx
interface IReport
{
void DoSomething();
}
class ReportApdapter : IReport
{
private readonly Report _report;
public ReportApdapter(Report report)
{
_report = report;
}
public void DoSomething()
{
_report.DoSomething();
}
}
class Report
{
public void DoSomething()
{
}
}
//You can use like this.
IReport report = new ReportApdapter(TheirApi.GetReport());
I need to have a wrapper class that exposes some properties of my entity class called ProfileEntity.
I tried doing it by deriving from this entity and then creating properties that return specific entity properties, but it says I cannot cast from ProfileEntity to ProfileEntityWrapper.
When I try to put the return values of a method that returns a 'ProfileEntity' into the wrapper I get the above error.
How do I create such a wrapper class that is castable?
Example
class ProfileEntityWrapper : ProfileEntity
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class Someclass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity; // example of method returning this object
}
}
public class SomeOtherlClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
ProfileEntityWrapper ew = (ProfileEntityWrapper)sc.SomeMethod(); // Cannot do this cast!!!
}
}
You cannot cast an object of ProfileEntity to ProfileEntityWrapper.
var entity = new ProfileEntity(); // this object is only of type ProfileEntity
var wrapper = new ProfileEntityWrapper(); // this object can be used as both ProfileEntityWrapper and ProfileEntity
You probably want to return a ProfileEntityWrapper in SomeMethod():
public class Someclass
{
public ProfileEntity SomeMethod()
{
return new ProfileEntityWrapper(); // it's legal to return a ProfileEntity
}
}
No, that is not possible.
To accomplish this problem you can maybe try this one:
public class ProfileEntity
{
public string ProfileEntityName { get; set; }
}
public class ProfileEntityWrapper
{
public ProfileEntityWrapper(ProfileEntity entity)
{
Entity = entity;
}
public ProfileEntity Entity { get; private set; }
public string Name
{
get
{
return Entity.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
// example of method returning this object
ProfileEntity temp = new ProfileEntity();
return temp;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
//Create a new Wrapper for an existing Entity
ProfileEntityWrapper ew = new ProfileEntityWrapper(sc.SomeMethod());
}
}
If you are allowed to edit the ProfileEntity class, or if the ProfileEntity class is a generated partial class, you could add an interface instead of using a wrapper. You wouldn't need to do any casting with an interface either. Example:
public interface IProfile
{
string Name { get; }
}
public partial class ProfileEntity : IProfile
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
IProfile ew = sc.SomeMethod();
}
}
The IProfile instance will only provide access to the Name property.
This's no correct code from polymorphism aspect.
If we will take the famous polymorphism example when there're base Shape class and Circle, Polygon and Rectangle classes that extend the Shape class, your code will try to cast some shape into circle and as you understand this's invalid casting operation.
So to make this code work you must be sure that SomeClass.SomeMethod() will return instance of ProfileEntityWrapper or perform type check before the casting, like this:
ProfileEntity temp = sc.SomeMethod();
if(temp is ProfileEntityWrapper)
ProfileEntityWrapper ew = (ProfileEntityWrapper) temp;