界面我如何获得任何客户?

Interface how do I get any Customer?

我们有一个与通用客户 (gold/silver) 的接口,现在假设我将最后创建的客户存储在某处 (Cache/DB/etc)。

如何创建 returns 客户类型的 GetCustomer 方法。 我应该将 GetCustomer 添加到基础 class 或接口或其他地方吗?以及我们如何使用 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;

    }
}

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

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

所有这些都是为了让您不必在每次创建实现该接口的新客户 class 时都编写冗余代码。

您似乎正在尝试使用 classic Factory Method

就个人而言,对于简单的 classes,就像你问的那样,我会在基础 class 上添加一个静态方法,如下所示:

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

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

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

但是假设您想要一个同时适用于两者的缓存。您将引入一个 non-generic 基本接口:

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;

你设计的问题是MakeCustomer是customers的一个实例方法。这意味着,您必须创建一个客户才能致电 MakeCustomer。也就是说,这个设计是行不通的!

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

泛型类型参数是多余的。

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属性。它可以在基础 class 中进行抽象,以强制具体的客户 class 来实现它。

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

另请参见维基百科上的 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}");
}

打印:

Frank is Gold
Jack is Silver

查看工作示例:https://dotnetfiddle.net/BiAskT