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");
}
}
Related
I am using FluentValidator in a C# project.
I would like to make a generic method that can validate data from 2 possible types:
public class MyClassAValidator : AbstractValidator<MyClassA> {...}
public class MyClassBValidator : AbstractValidator<MyClassB> {...}
public void MyMt<T>(T param)
{
AbstractValidator<T> validator = null;
if(param is MyClassA)
{
var validator = new MyClassAValidator(); // Generatescompiler error
}
else if (cCOSLDto is CCOSLLoyerDto)
{
validator = new MyClassBValidator(); // Generatescompiler error
}
ValidationResult result = validator.Validate(param);
}
Compiler cannot convert MyClassAValidator() or MyClassBValidator() to AbstractValidator
How can I handle this?
I suspect (just a suspicion though) that it would work if I set a base class to MyClassA and MyClassB. But I would like to avoid this if possible as MyClassA and MyClassB are actually DTO classes so I would prefer them to stay without inheritence relationship.
Actually, if you need to validate two different types of objects in one method, you dont have to mess with inheritance from a generic class.
There is an easy way to do this. Any Validate method returns ValidationResult, so you can use something like this:
using FluentValidation;
using FluentValidation.Results;
using System;
namespace FluentValidatorTranslation
{
class Program
{
static void Main(string[] args)
{
}
public ValidationResult MyMt<T>(T param)
{
ValidationResult result;
if(param is MyClassA myClassA)
{
var validator = new MyClassAValidator();
result = validator.Validate(myClassA);
}
else if (param is MyClassB myClassB)
{
var validator = new MyClassBValidator();
result = validator.Validate(myClassB);
}
else
{
throw new ArgumentException("Type not supported");
}
return result;
}
}
public class MyClassA { }
public class MyClassB { }
public class MyClassAValidator : AbstractValidator<MyClassA>
{
}
public class MyClassBValidator : AbstractValidator<MyClassB>
{
}
}
I am looking for a way to support multi level of inheritance for generic type constraint.
Common generic interface
public interface ICommon<T>
{
T OrignalData {get;set;}
string ChangeJson {get;set;}
T Merged {get;set;}
void Inject();
}
Common base class implements ICommon
public class Base <T>: ICommon<T>
{
public T OrignalData {get;private set;}
public string ChangeJson {get;set;}
public T Merged {get;private set;}
public void Inject(T orignal)
{
if (orignal == null)
return;
var settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
dynamic merged = orignal.Clone();
JsonConvert.PopulateObject(this.ChangeJson, merged, settings);
this.Merged = merged;
this.Orignal = orignal;
}
}
Department class inherits Base class
public class Deparment : Base<Deparment>
{
}
OrgnizationDepartment class inherits Deparment
public class OrgnizationDepartment : Deparment
{
}
class View expect ICommon must implement on passed calls
public class View<T> where T : ICommon<T>
{
//This class is totally dynamic to visualize any json data along with old and new value of requested json for any class like department or org..
}
Test
public class Test
{
public void TestConstraint()
{
//No error
var deptView = new View<Deparment>();
//Error as Base not directly implemented on OrgnizationDepartment
var orgView = new View<OrgnizationDepartment>();
}
}
how do I define my constraint that should support for multi level as well.
One way out of this would be "composition over inheritance".
Here is a naive example, that is still relatively close to your code:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
//No error
var deptView = new View<Deparment>();
//Formerly Error
var orgView = new View<OrgnizationDepartment>();
}
}
public interface ICommon<T> where T : ICloneable
{
// returns a tuple
(T,T,string) Inject(T original, string change);
}
public class Base <T>: ICommon<T> where T : ICloneable
{
// we can reuse this...
private readonly JsonSerializerSettings settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
public (T,T,string) Inject(T original, string change)
{
if (original is null)
return default;
// this forces T to implement ICloneable ... just saying...
dynamic merged = original.Clone();
JsonConvert.PopulateObject(change, merged, settings);
return (original, merged, change);
}
}
public class Deparment : ICloneable, ICommon<Deparment>
{
// could also be created in ctor. Maybe use Ctor injection.
private readonly Base<Deparment> common = new Base<Deparment>();
public object Clone(){return this;} // this is of course nonsense. Clone properly! I did this to avoid dotnetfiddle screaming at me.
public (Deparment, Deparment, string) Inject(Deparment original, string change){
return common.Inject(original, change);
}
}
public class OrgnizationDepartment : ICloneable, ICommon<OrgnizationDepartment>
{
private readonly Base<OrgnizationDepartment> common = new Base<OrgnizationDepartment>();
public object Clone() {return this;}
public (OrgnizationDepartment, OrgnizationDepartment, string) Inject(OrgnizationDepartment original, string change){
return common.Inject(original, change);
}
}
Problem: I have many file types that I want to parse. Each one parses a file and returns a result (List<>) of objects. I want to have just one IFileParser interface and specify the parser type and return set at time of calling Parse
I have an interface like this
public interface IFileParser
{
TResponse Parse<TFileParserType,TResponse>(string file);
}
being injected into a service like this
private readonly IFileParser _fileParser;
public CarService(IFileParser fileParser)
{
_fileParser = fileParser;
}
being used
var cardatas = _fileParser.Parse<CarFileParser, List<CarData>>("car.txt");
var bikedatas = _fileParser.Parse<BikeFileParser, List<BikeData>>("bike.txt");
implementation - this part does not work...why?
error returned is
Cannot implicitly convert type 'System.Collections.Generic.List<CarData>' to 'System.Collections.Generic.List<TResponse>'
public class CarFileParser : IFileParser
{
public List<CarData> Parse(string filePath)
{
return new List<CarData>() //does not work...why??
}
public TResponse Parse<TType, TResponse>(string file)
{
throw new NotImplementedException();
//this is what it should be
//but how do I return a List<CarData>
}
}
Not claiming this to be the Answer. Does this help:
public interface IFileParser<TResponse>
{
TResponse Parse(string file);
}
public class CarFileParser : IFileParser<List<CarData>>
{
public List<CarData> Parse(string file)
{
throw new NotImplementedException();
}
}
first of all, return type should match with return value:
public List<CarData> Parse(string filePath)
{
return new List<CarData>() //Will work..
}
while doing the type conversion, a list cannot be convert to class. If you want this, create a property in class.
var cardatas = _fileParser.Parse<CarFileParserList, List<CarData>>("car.txt");
class CarFileParser
{
public List<CarFile> CarFileParserList{get;set;}
}
public class CarFile
{
//create property here
}
then you can use this code:
var cardatas = _fileParser.Parse<List<CarFile>, List<CarData>>("car.txt");
var carFileParser= new CarFileParser();
carFileParser.CarFileParserList=cardatas;
If it always returns a list, maybe try
List<TResponse> Parse<TFileParserType, TResponse>(string file);
and then
List<CarData> cardatas = _fileParser.Parse<CarFileParser, CarData>("car.txt");
(or possibly ICollection / IEnumerable)
In general, I would prefer to implement the type / interface like this. Not sure if this works with your injection.
// Put the type of data on the interface / type
public interface IFileParser<TData>
{
IEnumerable<TData> Parse(string file);
}
// Implement the interface
public class CarParser : IFileParser<CarData>
{
...
}
// The method where to inject the implementation:
public IEnumerable<TData> Parse<TData>(IFileParser<TData> parser, string file)
{
return parser.Parse(file);
}
// The implementations would have to be injected here:
private readonly IFileParser<CarData> _carFileParser;
private readonly IFileParser<BikeData> _bikeFileParser;
var carData = Parse(_carFileParser, file);
var bikeData = Parse(_bikeFileParser, file);
I am quite new to the C# world and I apologize if the Question title not exactly match the content. But now to my Problem:
I have the following construct:
public interface IClass<TEnum>
{
Dictionary<TEnum, ISecondClass> dictionary { get; }
}
public abstract class ClassBase<TEnum> : IClass<TEnum>
{
public abstract Dictionary<TEnum, ISecondClass> dictionary { get; protected set; }
}
public class ConcreteClass : ClassBase<ConcreteClass.Concrete>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Other : ulong
{
}
}
My goal is to instantiate all existing concrete classes based on it's enums, store all instances in a dictionary and later invoke some methods on each object.
I am not sure if this is even possible?
I am glad for any hint on this!
If I understand what you're trying to do, it sounds like a version of the Multiton Pattern. You may find it useful to research that.
From Wikipedia's example Multiton code:
class FooMultiton
{
private static readonly Dictionary<object, FooMultiton> _instances = new Dictionary<object, FooMultiton>();
private FooMultiton() {}
public static FooMultiton GetInstance(object key)
{
lock (_instances)
{
FooMultiton instance;
if (!_instances.TryGetValue(key, out instance))
{
instance = new FooMultiton();
_instances.Add(key, instance);
}
}
return instance;
}
}
This isn't directly pasteable into your class, but since you're looking for hints, I think it should point you in the right direction.
One word of caution about the above code: The method GetInstance will alter the dictionary if key isn't found. Personally, I associate the "Get" prefix with read-only methods. I'd either rename GetInstance or split it into two methods.
I'm not really sure what you mean by "instantiate all existing concrete classes based on it's enums", though. Can you clarify that?
Use Activator.CreateInstance() to create concrete classes' objects and store them into dictionary.
Pass your string classname from Enum and create dynamic class objects. Store them into Dictionary<Enum, ISecondClass>
myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");
or
var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
While retrieving, based on your enum key, you know what type of instance value represents.
I don't understand a goal of the sample code, but you can write some thing like this:
public interface IClass
{
void MethodToDynamicInvoke();
}
public abstract class ClassBase<T>
: IClass
{
private Dictionary<Type, List<IClass>> instances = new Dictionary<Type, List<IClass>>();
public ClassBase()
{
List<IClass> list;
if (!instances.TryGetValue(typeof(T), out list))
{
list = new List<IClass>();
instances.Add(typeof(T), list);
}
list.Add(this);
}
public abstract void MethodToDynamicInvoke();
public void InvokeMetodOnClassesWithSameEnum()
{
List<IClass> list;
if (instances.TryGetValue(EnumType, out list))
{
foreach (var instance in list)
{
instance.MethodToDynamicInvoke();
}
}
}
}
public class ConcreteClass
: ClassBase<ConcreteClass.Concrete>
{
public ConcreteClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public OtherClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Other : ulong
{
}
}
Is it possible to do something like the following:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
Basically, I want a transparent way to wrap a base class inside of other functionality. One example I've thought of is a custom Settings Provider which transparently audits the settings passed through it.
public class SettingsAuditor : SettingsProvider
{
public SettingsAuditor(SettingsProvider o)
{
base = o;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
base.SetPropertyValues(context, propvals);
}
}
Then I could do the following:
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
And all changes would go through the overridden SetPropertyValues before passing to the original object.
I could use a private SettingsProvider member, but then I either cannot inherit from SettingsProvider, or have an entire SettingsProvider (base) not being used at all.
I'm using C# 4.0 and .Net 4.0.
You cannot do base = o;
What you're looking for is the Decorator Pattern), which is a way to compositionally add functionality at runtime (vs. inheritance).
Instead of trying to set the base, you just contain the inner member. As long as the wrapper implements the same interface or base class as the inner object, you can pass back the new wrapper. You can wrap as many decorators as you want.
Consider:
public interface ICar
{
void Drive();
}
public class Car : ICar
{
public void Drive()
{
Console.WriteLine("vroom");
}
}
public class BuckleUp : ICar
{
ICar car;
public BuckleUp(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("click!");
car.Drive();
}
}
public class CheckMirrors : ICar
{
ICar car;
public CheckMirrors(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("mirrors adjusted");
car.Drive();
}
}
Now consider you have a method that accepts an ICar and tells it to drive. You could give it a Car, and it would work, but you could also wrap that car in a BuckleUp and a CheckMirrors and you wouldn't have to change that method at all. You've modified functionality through composition using the Decorator Pattern.
No. This looks like it should be a Composition vs Inheritance issue. You need to evaluate whether you are a "is a" or a "has a."
A little help for your journey
This is not a complete implmentation and it could probably be done much cleaner with expression trees... but this was a quick swing at faking AOP using DynamicObject with .Net 4.0.
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
No, but you could fake it:
public class SettingsAuditor
{
SettingsProvider #base;
public SettingsAuditor(SettingsProvider o)
{
#base = o;
}
public void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
#base.SetPropertyValues(context, propvals);
}
}
Note here, #base isn't the actual base, just a varaible named base