界面如何获得任何客户?

时间:2018-03-20 19:26:37

标签: c# generics interface abstract

我们有一个与通用客户(金/银)的接口,现在我可以说我存储了最后一个创建的cutomer(Cache / DB / etc)。

如何创建返回客户类型的GetCustomer方法。 我应该将GetCustomer添加到基类或接口或其他地方吗?以及我们如何使用GetCustomer?

希望这是有道理的。

interface ICstomerInterface<T>
{
    T MakeCustomer();
}   

public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
    public string Type { get; set; }
    public string Name { get; set; }
    // methods
    public abstract T MakeCustomer();

}

public class Gold : BaseCustomer<Gold>
{
    public override Gold MakeCustomer()
    {
        var customer = new Gold
        {
             Type= "Gold",
             Name = "Jack"
        };
        return customer;
    }
}

public class Silver : BaseCustomer<Silver>
{
    public override Silver MakeCustomer()
    {
        var customer = new Silver();
        customer.Name = "Jones";
        customer.Type = "Silver";
        return customer;

    }
}

4 个答案:

答案 0 :(得分:0)

您可以使用扩展方法获取客户类型(在静态类上):

public static Type GetCustomerType<T>(this ICstomerInterface<T> _customer)
{
    return typeof(T);
}

所有这些都意味着每次创建实现该接口的新Customer类时都不必创建冗余代码。

答案 1 :(得分:0)

您似乎正在尝试使用经典Factory Method

对于简单的类,就像你要问的那样,我会在基类上添加一个静态方法,如下所示:

public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
    public static BaseCustomer<T> GetLastCustomer()
    {
        // Get from storage, the last customer.
    }
}

这样,您的创建客户方法与您的获取客户方法是分开的,但仍可从任何地方访问。

答案 2 :(得分:0)

您的示例代码不包含可以包含所有客户的基本类型,即没有强类型变量可以包含BaseCustomer<Gold>BaseCustomer<Silver>。这两者之间没有类型兼容性,只有Dictionary<int>可以存储为Dictionary<string>(事实上,更糟糕的是,因为对象模型中没有协方差) 。鉴于这一事实,您的问题没有多大意义,因为您总是必须声明类型参数以在某处存储客户,因此无需在运行时学习该类型。

但是,让我们说你想要一个适合两者的缓存。您将引入一个非通用的基本接口:

public interface ICustomer
{ 
    Guid CustomerGuid { get; }
}

public abstract class BaseCustomer<T>: ICstomerInterface<T>, ICustomer
{
    ///etc....

现在您可以定义一个可以容纳所有客户的缓存:

var cache = new Dictionary<Guid,ICustomer>();
var gold = new Gold();
cache.Add( gold.CustomerGuid, gold );
var silver = new Silver();
cache.Add( silver.CustomerGuid, silver );

现在您可以通过其Guid检索任何客户:

var customer = cache[guid];

要确定其类型,只需使用

即可
bool isGold = customer is Gold;
bool isSilver = customer is Silver;

或者获取一个告诉你类型的字符串:

string type = customer.GetType().Name;

答案 3 :(得分:0)

您设计的问题是MakeCustomer是客户的实例方法。这意味着您必须创建一个客户才能调用MakeCustomer。换句话说,这种设计不起作用!

您有两种选择:只需在各自的构造函数中初始化客户,或者创建客户工厂。这必须是一个单独的类(静态或非静态)。

泛型类型参数是多余的。

public abstract class CustomerBase
{
    public CustomerBase(string name)
    {
        Name = name;
    }

    public abstract string Type { get; }
    public string Name { get; }
}

public class GoldCustomer : CustomerBase
{
    public GoldCustomer(string name)
      : base(name)
    {
    }

    public override string Type => "Gold";
}

public class SilverCustomer : CustomerBase
{
    public SilverCustomer(string name)
      : base(name)
    {
    }

    public override string Type => "Silver";
}

Type属性可以是仅限getter的属性。它可以在基类中抽象,以强制具体的客户类来实现它。

必须将名称传递给构造函数才能为不同的客户分配不同的名称。

另请参阅维基百科上的Abstract factory pattern

示例:

var customers = new List<CustomerBase> {
    new GoldCustomer("Frank"),
    new SilverCustomer("Jack")
};

foreach (CustomerBase c in customers) {
    Console.WriteLine($"{c.Name} is {c.Type}");
}

打印:

  

弗兰克是金子   杰克是银色的

参见工作示例:https://dotnetfiddle.net/BiAskT