Search code examples
c#genericsc#-2.0constraintsfilehelpers

Generic constraint for Constructor with string argument?


How to create a generic class that allows types which has constructor taking one string argument and implements ToString and implements Two functions as below.

    class Convert<T>:ConverterBase
        where T:new()
    {

        public override object StringToField(string from)
        {
            try
            {
                return new T(from);
            }
            catch (ArgumentException exception)
            {
                ThrowConvertException(from, exception.Message);
                return null;
            }
        }

        public override string FieldToString(object from)
        {
            return from.ToString();
        }

    }

Note: ConvertBase is a abstract class in FileHelpers csv reader library. I already have classes that corresponds to my fields in csv, didn't want to create seperate Classes that inherit ConvertBase inorder to use with the FileHelpres library.


Solution

  • Hi there you can create a base class that stores the converter function and implements both members, after that you can inherit from it and only provide the string to object convertion

    public abstract class Convert<T>:ConverterBase
    {
        private Func<string, T> ConverterFunction {get;set;}
    
        protected Convert(Func<string, T> converterFunction)
        {
            ConverterFunction = converterFunction;
        }
    
        public override object StringToField(string from)
        {
            try
            {
                return ConverterFunction(from);
            }
            catch (ArgumentException exception)
            {
                ThrowConvertException(from, exception.Message);
                return null;
            }
        }
    
        public override string FieldToString(object from)
        {
            return from.ToString();
        }
    
    }
    

    Later create some simple derived classes for example:

    public class ConvertMyClass:ConverterBase<MyClass>
    {
        public ConvertMyClass()
            :base(from => new MyClass(from)
        { 
        }
    }
    

    Hope this helps :) Remember to download the last stable version from: http://teamcity.codebetter.com/viewLog.html?buildId=lastSuccessful&buildTypeId=bt66&tab=artifacts&guest=1

    EDIT: Using Reflection you can try:

    class Convert<T>:ConverterBase
    {
    
        public override object StringToField(string from)
        {
            try
            {
                return Activator.CreateInstance(typeof(T), from);
            }
            catch (ArgumentException exception)
            {
                ThrowConvertException(from, exception.Message);
                return null;
            }
        }
    
        public override string FieldToString(object from)
        {
            return from.ToString();
        }
    
    }
    

    NOTE: Reflection is slow, so you must take that into account