将Linq查询结果转换为接口

4

我正在尝试编写一个Linq(针对对象)查询,将结果转换为接口,如下所示:

    var data = (from row in CicApplication.Vaporizer473Cache
                where row.Coater == coater
                select row).Cast<IVaporizerData>();

这似乎是唯一的方法,因为我无法在select中创建接口实例。 我有两个问题:

  1. 强制转换实际上是如何完成的? 它会在源中找到每个属性,并将其值复制到具有相同名称的接口属性中吗?

  2. 我在我的接口中有一个属性未包含在源中,但我想在此操作期间以某种方式设置其值。 这可能吗? 还是我需要在查询之后,在for each语句中执行它?

如果有帮助的话,数据源(Vaporizer473Cache)的类定义如下。 接口非常相似。

internal class Vaporizer473
{
    /// <summary>
    /// Gets or sets the Coater property
    /// </summary>
    public string Coater { get; set; }

    /// <summary>
    /// Gets or sets the CoaterTime property
    /// </summary>
    public DateTime? CoaterTime { get; set; }

    /// <summary>
    /// Gets or sets the TemperatureLeftTubeA property
    /// </summary>
    public double? TemperatureLeftTubeA { get; set; }

    /// <summary>
    /// Gets or sets the TemperatureLeftTubeB property
    /// </summary>
    public double? TemperatureLeftTubeB { get; set; }

    /// <summary>
    /// Gets or sets the TemperatureRightTubeA property
    /// </summary>
    public double? TemperatureRightTubeA { get; set; }

    /// <summary>
    /// Gets or sets the TemperatureRightTubeB property
    /// </summary>
    public double? TemperatureRightTubeB { get; set; }

}


1
不行;那只会引发一个“InvalidCastException”异常。 - SLaks
3个回答

5

尽管编译器不会对您提供的语法进行投诉,但它将无法运行。您不能将对象转换为它没有实现的接口。

Cast方法只是一个方便的方法,它尝试将给定的IEnumerable中的每个对象转换为您提供的通用类型。如果Vaporizer473实现了IVaporizerData,则您可以轻松地说:

var data = from row in CicApplication.Vaporizer473Cache
           where row.Coater == coater
           select (IVaporizerData)row;

其次:

我的界面中有一个属性不包含在源代码中,但我希望在操作期间以某种方式设置它的值。这可行吗?还是我需要在查询之后,在 for each 语句中进行此操作?

正如您现在所了解的那样,您的类将必须实现您接口中的属性。(您可以明确地这样做,以便不会影响到您实际类的实现和 IntelliSense 等内容。) 使用复杂的 Select 委托可以在运行时设置值,但这不是 LINQ 的初衷,我强烈不建议这样做。 在这种情况下,使用 for 循环是适当的。

请记住,如果您修改来自缓存的项,您将修改原始对象而不是它们的副本。 这可能会产生深远的影响。 您可能需要创建表示正在查找的数据的新对象。


好的。如果我理解正确的话,我的Vaporizer473类需要实现IVaporizerData接口吗? - Randy Minder
@RandyMinder:没错。如果你想要对该接口进行强制转换,那么它必须实现该接口。 - StriplingWarrior

1
回答你的第一个问题,是的,就是这样做。但是看了你的代码,似乎 Vaporizer473 类没有实现 IVaporizorData 接口。假设这只是一个疏忽?如果不是,你需要实现该接口才能使 Cast<>() 调用起作用。
至于你的第二个问题,是的,你可以在 for-each 块之后设置它,或者你可以使用 Select 同时设置属性和进行转换,像这样:
CicApplication.Vaporizer473Cache
.Where( r => r.Coater = coater)
.Select((r) => {
   r.SomeProperty = somevalue;
   return r as IVaporizerData
});

是的,看来这是一个疏忽。谢谢。 - Randy Minder

1
  1. 非常简单。将一个对象转换为另一种类型并不意味着创建另一个对象。它只是同一个对象的不同“视图”。您的类必须实现接口才能这样做。因此,强制转换意味着相同的对象仍然在可枚举中。

  2. 由于在强制转换对象时不会创建新对象,因此无法设置接口的额外属性值。但这也意味着您的对象已经具有该属性,因为您的对象正在实现该接口。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接