将Linq查询结果转换为接口

时间:2012-12-11 19:28:15

标签: c# linq interface

我试图编写一个Linq(到Objects)查询,将结果强制转换为接口,如下所示:

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

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

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

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

  3. 如果有帮助,数据源的类定义(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; }
    

    }

3 个答案:

答案 0 :(得分:4)

即使编译器不会抱怨您提供的语法,它也不会运行。您无法将对象强制转换为未实现的接口。

Cast方法只是一种方便的方法,它尝试将给定IEnumerable中的每个对象强制转换为您提供的泛型类型。如果Vaporizer473 实施IVaporizerData,那么您可以轻松地说:

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

其次:

  

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

正如您现在已经想到的那样,您的课程必须在您的界面中实现该属性。 (你可以这样做explicitly所以它不会在你的实际类实现上使用intellisense等等。)可能通过使用复杂{{1}来设置值委托,但它不是LINQ的用途,我会高度劝阻它。这是一个Select循环是适当的事情。

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

回答你的第一个问题,是的,这就是它的完成方式。但是,查看代码时,Vaporizer473类似乎没有实现IVaporizorData。假设这只是一个疏忽?如果没有,您将需要实现该接口,以便Cast<>()调用工作。

关于你的第二个问题,是的,你可以在之后的每个块中设置它,或者你可以使用Select来设置属性并进行强制转换,如下所示:

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