简体   繁体   English

具有字符串参数的Constructor的通用约束?

[英]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. 如何创建一个泛型类,允许类型具有构造函数获取一个字符串参数并实现ToString并实现如下两个函数。

    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. 注意:ConvertBase是FileHelpers csv阅读器库中的抽象类。 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. 我已经有了与csv中的字段对应的类,不想创建继承ConvertBase的单独类,以便与FileHelpres库一起使用。

There is no way to use the constructor constraint ( new() ) to constrain to anything other than an empty constructor. 没有办法使用构造函数约束( new() )来约束除空构造函数之外的任何东西。 One way to work around this though is to use a lambda expression. 解决这个问题的一种方法是使用lambda表达式。 For example 例如

class Convert<T>:ConverterBase {
  private Func<string, T> _factory;
  public (Func<string, T> factory) {
    _factory = factory;
  }

  public override object StringToField(string from) {
    try {
      return _factory(from);
    } ...
  }
}

Now I can create instances of Convert<T> and use a lambda expression to forward to the constructor of the type 现在我可以创建Convert<T>实例并使用lambda表达式转发到该类型的构造函数

new Convert<Foo>(s => new Foo(s));

EDIT C# 2.0 implementation since the OP is stuck with 2.0 编辑 C#2.0实现,因为OP坚持2.0

public delegate TResult Func<T, TResult>(T arg);

new Convert<Foo>(delegate (string s) { return new Foo(s); });

You can't. 你不能。 You can only create a constraint that enforces, that your class has a parameterless constructor . 您只能创建一个强制执行的约束,即您的类具有无参数构造函数 The constraint for that is new() , as you know. 正如您所知,对此的约束是new()

ToString() is available on every type, because it is defined on Object and every type inherits from Object . ToString()在每种类型都可用,因为它是在Object上定义的,并且每个类型都继承自Object However, you can't know or enforce, whether your type provides it's own implementation of ToString() . 但是,您无法知道或强制执行,您的类型是否提供了自己的ToString()

To make sure, the type parameter implements two specific methods, put them into an interface and constrain the type parameter to that interface and make your class implement that interface. 为了确保,type参数实现了两个特定的方法,将它们放入一个接口并将type参数约束到该接口,并使您的类实现该接口。

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 希望这会有所帮助:)请记住从以下网址下载最新的稳定版本: http//teamcity.codebetter.com/viewLog.html?buildId =lastSuccessful&buildId = bt66&tab = artifacts&aguest = 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 注意:反射很慢,因此您必须考虑到这一点

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM