如何在接口方法的实现中强制使用特定值?

时间:2012-05-04 19:06:32

标签: c# .net interface

通过示例可以更好地解释这一点。目前我有这样的事情:

public class Car {
    internal string SaleCode {get; set;} //Spring, Summer, ...
    public string Name {get; set; }  //Model name
}

public interface ICarFactory 
{
    Car GetSummerSaleCar();
    Car GetSpringSaleCar();
}

public class FordFactory : ICarFactory 
{
    public Car GetSummerSaleCar() {
        return new Car() {Name="Fiesta"};
    }
    public Car GetSpringSaleCar() {
        return new Car() {Name="Fusion"};
    }
}

public class CarProvider {
    public void ProduceCars(ICarFactory factory) {
        var inventory = new List<Car>();
        Car car = null;
        car = factory.GetSummerSaleCar();
        car.SaleCode = "SMR";
        inventory.Add(car);

        car = factory.GetSpringSaleCar();
        car.SaleCode = "SPG";
        inventory.Add(car);
    }
}

对于每种方法,汽车的SaleCode应始终相同,因此CarFactory实现不应设置此值。现在我在CarProvider类中设置它,但我想知道是否有办法将其从界面中取出。我唯一能想到的是在接口中使用应用于方法定义的属性,我可以在其中设置类型,但我觉得必须有另一种选择。

想法?

更新

如果你想知道,当我提到在界面中为每个方法添加一个属性时,这就是我所说的:

public class SaleAttribute : Attribute
{
    public string Code { get; set; }
}


public interface ICarFactory
{
    [Sale(Code = "SMR")]
    Car GetSummerSaleCar();
    [Sale(Code = "SPG")]
    Car GetSpringSaleCar();
}

public void ProduceCars(ICarFactory factory)
{
    var inventory = new List<Car>();
    foreach (var method in typeof(ICarFactory).GetMethods())
    {
        String carType = null;
        var attributes = method.GetCustomAttributes(typeof(SaleAttribute), false);
        if (attributes.Length == 1)
        {
            saleCode = ((SaleAttribute)attributes[0]).Name;
            Car car = (Car)method.Invoke(factory, null);
            car.SaleCode = saleCode;
            inventory.Add(car);
        }
    }
}

这具有额外的好处,即如果在界面中添加方法,则不需要修改CarProvider。缺点显然是与Reflection相关的开销(性能和维护)。

UPDATE2

我将示例从使用汽车类型更改为销售代码,因为这更好地反映了我的情况。

2 个答案:

答案 0 :(得分:3)

Mike我认为最好的方法是使用抽象类型Car和两个派生类:CompactCar和MediumCar。

public abstract class Car { 
    internal string Type {get; protected set;} //Compact, Medium, Large, ... 
    public string Name {get; set; }  //Model name 
} 

public class CompactCar : Car
{
     public CompactCar() { this.Type = "Compact"; }
}

public class MediumCar : Car
{
     public MediumCar() { this.Type = "Compact"; }
}

因此您可以返回特定类型,如:

public interface ICarFactory      
{     
    CompactCar GetCompact();     
    MediumCar GetMedium();     
}  
public class FordFactory : ICarFactory    
{   
    public CompactCar GetCompact() {   
        return new CompactCar() {Name="Fiesta"};   
    }   
    public MediumCar GetMedium() {   
        return new MediumCar() {Name="Fusion"};   
    }   
}  

这对使用它的源代码影响最小,因为它仍然可以引用具有抽象类型Car的汽车。

答案 1 :(得分:0)

CarType.Create(Medium)而不是new Car怎么样?

我建议使用名为CarType

的工厂
public class CarType{
   public class CarType(instName){
      this.instName = instName;
   }
   public Car Create(){
      return new Car(){Type=instName;}
      //or alternatively, if you have more implementations for the cars
      //return (Car)Activator.CreateInstance(this.instName);
   }
   public static CarType Compact = new CarType("Compact");
   public static CarType Medium = new CarType("Medium");
}

,用法是

Medium.Create(){Name="Fiesta";}

但那仍然属于CarFactorys方法,所以对你没那么多帮助......