没有new()的泛型

Pet*_*vor 7 c# generics

我的项目中有十几种方法(C#2.0),如下所示:

internal bool ValidateHotelStayEntity(DataRow row)
{
    return (new HotelStayEntity(row)).Validate();
}
Run Code Online (Sandbox Code Playgroud)

......但是对于不同的"实体"类.(好吧,不是那么琐碎,我在这里简化了代码.)

它似乎是泛型的一个很好的候选者,我想出了这个:

internal bool ValidateEntity<T>(DataRow row) where T : EntityBase
{
    return (new T(row)).Validate();
}
Run Code Online (Sandbox Code Playgroud)

当然我得到"无法创建类型参数'T'的实例,因为它没有new()约束"错误.

问题是这些"实体"类没有公共无参数构造函数,也没有在之后添加"行"数据的方法.由于EntityBase是公司框架的一部分,我无法控制它(即我无法改变它).

有没有办法解决?

Jon*_*eet 15

一种简单的方法是提供工厂功能:

internal bool ValidateEntity<T>(DataRow row, Func<DataRow, T> factory)
    where T : EntityBase
{
    return factory(row).Validate();
}
Run Code Online (Sandbox Code Playgroud)

并致电:

bool valid = ValidateEntity(row, x => new Foo(x));
Run Code Online (Sandbox Code Playgroud)

请注意,在这一点上,它比仅仅打电话更复杂

bool valid = new Foo(row).Validate()
Run Code Online (Sandbox Code Playgroud)

首先...

你真正想要在真实环境中实现什么并不是很清楚,但这种工厂/提供商方法在其他时候肯定是有用的.请注意,调用工厂的委托,也可以明显比使用更快的new T()与约束,正如我前一阵子博客.在很多情况下,不过是不可知的,但值得了解.

编辑:对于.NET 2.0兼容性,您需要自己声明委托,但这很容易:

public delegate TResult Func<T, TResult>(T input);
Run Code Online (Sandbox Code Playgroud)

如果您真的使用的是C#2(而不是C#3,目标是.NET 2.0),那么您也无法使用lambda表达式,但您仍然可以使用匿名方法:

bool valid = ValidateEntity(row, delegate(DataRow x) { return new Foo(x); });
Run Code Online (Sandbox Code Playgroud)


vc *_* 74 3

另一种方法可能是涉及反射,但代价是编译时检查和性能下降:

internal bool ValidateEntity<T>(DataRow row)
{ 
   object entity = Activator.CreateInstance(typeof(T), new object[] { row });
   MethodInfo validate = typeof(T).GetMethod("Validate");
   return (bool) validate.Invoke(entity, new object[]);
}
Run Code Online (Sandbox Code Playgroud)

请注意,即使实体没有共同的祖先,这也会起作用