2012-12-11 87 views
3

我试图写一个LINQ(到对象)查询连铸结果的接口,如下图所示:铸造LINQ查询结果到接口

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

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

  1. 演员是如何实际完成的?它会找到源中的每个属性并将其值复制到具有相同名称的接口属性?

  2. 我有一个属性在我的界面中不包含在源中,但我想以某种方式在此操作中设置其值。这可能吗?或者我需要在查询之后执行它,在每个语句中?

如果有帮助,数据源(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

回答

4

即使编译器不会与您所提供的语法抱怨,它不会运行。你不能将一个对象转换成它没有实现的接口。

Cast方法只是一种简便的方法,它试图将给定IEnumerable中的每个对象转换为您提供的泛型类型。如果Vaporizer473 没有实施IVaporizerData,那么你可以很容易地说:

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

其次:

我有没有包含在源在我的接口属性,但我会喜欢在此操作过程中以某种方式设置其值。这可能吗?或者我需要在查询之后执行它,在每个语句中?

正如你现在已经发现的那样,你的类将不得不在你的接口中实现这个属性。 (你可以这样做explicitly,这样它就不会在你的实际类实现等问题上拥挤智能感知)。当你使用复杂的Select委托时,它可能会设置,但这不是LINQ的目的,我会极力阻止它。这是一个for循环是适当的事情。

请记住,如果您修改来自缓存的项目,那么您将修改原始对象而不是它们的克隆。这可能有深远的影响。您可能希望创建新的对象来代表您正在查找的数据。

+0

好的。所以如果我正确理解你的话,我的Vaporizer473类需要实现IVaporizerData? –

+0

@RandyMinder:是的。如果你想能够对该接口进行转换,那么它必须实现接口。 – StriplingWarrior

1
  1. 很简单。 铸造一个对象到另一个类型并不意味着另一个对象被创建。对同一个对象来说,它是一个简单的“视图”。您的班级必须实施该界面才能够做到这一点。所以演员表示相同的对象仍然在可枚举中。

  2. 由于您在转换对象时未创建新对象,因此无法设置接口的额外属性的值。但是这也意味着你已经拥有了你的对象中的属性,因为你的对象正在实现这个接口。

1

要回答你的第一个问题,是的,这是如何完成的。然而,看着你的代码,似乎Vaporizer473类没有实现IVaporizorData。假设这只是一个疏忽?如果不是,则需要实施该接口才能使Cast<>()呼叫生效。

关于你的第二个问题,是的,你可以将其设置在换每个块之后,或者你可以使用一个Select既设置属性,做演员,像这样:

CicApplication.Vaporizer473Cache 
.Where(r => r.Coater = coater) 
.Select((r) => { 
    r.SomeProperty = somevalue; 
    return r as IVaporizerData 
}); 
+0

是的,似乎是一个疏忽。谢谢。 –