不带new()的泛型

本文关键字:泛型 new 不带 | 更新日期: 2023-09-27 18:21:46

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

internal bool ValidateHotelStayEntity(DataRow row)
{
    return (new HotelStayEntity(row)).Validate();
}

但用于不同的"实体"类。(好吧,不是那么琐碎,我已经简化了这里的代码。)

它看起来像是仿制药的一个很好的候选者,我想出了这个:

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

当然,我得到了"无法创建类型parameter‘T’的实例,因为它没有new()约束"的错误。

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

有办法解决这个问题吗?

不带new()的泛型

一个简单的方法是提供一个工厂函数:

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

并呼叫:

bool valid = ValidateEntity(row, x => new Foo(x));

请注意,在这一点上,它比仅仅调用更复杂

bool valid = new Foo(row).Validate()

首先。。。

目前还不清楚你在实际环境中想要实现什么,但这种工厂/提供商的方法在其他时候肯定会很有用。注意,调用工厂委托也可能比使用带约束的new T()快很多,正如我不久前在博客中所写的那样。在许多情况下是不可逆的,但值得了解。

编辑:为了与.NET 2.0兼容,您需要自己声明委托,但这很容易:

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

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

bool valid = ValidateEntity(row, delegate(DataRow x) { return new Foo(x); });

另一种方法可能是以编译时检查和降低性能为代价进行反射:

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[]);
}

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

@JohnLaunchers的工厂方法解决方案示例:

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

您可以这样做:

internal bool ValidateEntity<T>(DataRow row) where T : EntityBase 
{
     return ((T)Activator.CreateInstance(typeof(T), new object[] { row })).Validate(); 
}