Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 型铸造与工厂模式_C#_Factory Pattern - Fatal编程技术网

C# 型铸造与工厂模式

C# 型铸造与工厂模式,c#,factory-pattern,C#,Factory Pattern,我很难弄清楚如何在我试图创建的DTO映射器中实现工厂模式。我很确定我需要重新考虑我的设计。下面是一个非常小的例子,说明了我的想法: public abstract class Person { public string Name { get; set; } public decimal Salary { get; set; } } public class Employee : Person { public Employee() {

我很难弄清楚如何在我试图创建的DTO映射器中实现工厂模式。我很确定我需要重新考虑我的设计。下面是一个非常小的例子,说明了我的想法:

    public abstract class Person
{
    public string Name { get; set; }
    public decimal Salary { get; set; }
}

public class Employee : Person
{
    public Employee()
    {
        this.Salary = 20000;
    }

}

public class Pilot : Person
{
    public string PilotNumber { get; set; }

    public Pilot()
    {
        this.Salary = 50000;
    }
}

public static class PersonFactory
{
    public static Person CreatePerson(string typeOfPerson)
    {
        switch (typeOfPerson)
        {
            case "Employee":
                return new Employee();
            case "Pilot":
                return new Pilot();
            default:
                return new Employee();
        }
    }
}
以及使用工厂:

Person thePilot = PersonFactory.CreatePerson("Pilot");
        ((Pilot)thePilot).PilotNumber = "123ABC";
我如何在不向飞行员输入飞行员号码的情况下加载飞行员号码??这样做是错误的吗?我可以把飞行员号码放在Person类中,但是Employee会继承这个号码,这不是我想要的。我能做什么

谢谢


-Jackson

当对象在实现上不同时,最好使用工厂模式,而不是接口。在您的情况下,工厂模式不太有利,您最好直接创建对象(或者其他模式更好)。

是否必须使用字符串来传递所需的类型?您可以使用泛型:

public static T CreatePerson<T>() where T : Person
public static T CreatePerson(),其中T:Person
现在很难说这是否会起作用,因为我们不知道你在CreatePerson中真正在做什么的细节。如果它只是调用一个无参数构造函数,这很简单:

public static T CreatePerson<T>() where T : Person, new()
{
    return new T();
}
public static T CreatePerson(),其中T:Person,new()
{
返回新的T();
}

然而,这也是毫无意义的,因为调用方可以这样做。仿制药在你的实际情况下可行吗?如果没有,你能解释一下为什么没有,我们可以试着解决这个问题吗?

解决这个问题没有简单的方法

要使用PilotNumber属性,您需要Pilot类型。使用工厂模式意味着你放弃了不同的子类型的人

如果有什么安慰的话BCL也有类似的模式

 var req = WebRequest.CreateRequest("http://someUrl");
 ((HttpWebRequest)req).Contentlenght = ...;

您可以将特定类型的方法添加到PersonFactory类中,或者添加一个泛型的
CreatePerson()
方法,但这只有在调用方已经知道它应该接收什么类型的人时才有用。也许是这样,也许不是

在这种情况下,我希望实际调用PersonFactory.CreatePerson的代码不会知道或关心返回的是什么类型的人。如果在这一点之后您有一些代码已经知道或知道您拥有的person对象的类型,那么您只需将其强制转换

下面是一个代码示例,演示了在工厂和不同的使用场景中可以执行的操作,试图解释何时只需要强制转换或何时不需要强制转换

public static class PersonFactory
{
    public static Person CreatePerson()
    {
        return new Person();
    }

    public static Employee CreateEmployee()
    {
        return new Employee();
    }

    public static Pilot CreatePilot()
    {
        return new Pilot();
    }

    public static T CreatePerson<T>()
        where T : Person
    {
        return (T)CreatePerson(typeof(T));
    }

    public static Person CreatePerson(Type type)
    {
        if (type == typeof(Person))
            return CreatePerson();
        else if (type == typeof(Employee))
            return CreateEmployee();
        else if (type == typeof(Pilot))
            return CreatePilot();
        else
            throw new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Unrecognized type [{0}]", type.FullName), "type");
    }

    public static Person CreatePerson(string typeOfPerson)
    {
        switch (typeOfPerson)
        {
            case "Employee":
                return CreateEmployee();
            case "Pilot":
                return CreatePilot();
            default:
                return CreateEmployee();
        }
    }
}



class UsageExample
{
    Person GetPerson()
    {
        Pilot p;
        p = (Pilot)PersonFactory.CreatePerson("Pilot"); // this code already knows to expect a Pilot, so why not just call CreatePilot or CreatePerson<Pilot>()?
        p = PersonFactory.CreatePilot();
        p = PersonFactory.CreatePerson<Pilot>();
        return p;
    }

    Person GetPerson(Type personType)
    {
        Person p = PersonFactory.CreatePerson(personType);
        // this code can't know what type of person was just created, because it depends on the parameter
        return p;
    }

    void KnowledgableCaller()
    {
        Type personType = typeof(Pilot);

        Person p = this.GetPerson(typeof(Pilot));
        // this code knows that the Person object just returned should be of type Pilot

        Pilot pilot = (Pilot)p;
        // proceed with accessing Pilot-specific functionality
    }

    void IgnorantCaller()
    {
        Person p = this.GetPerson();
        // this caller doesn't know what type of Person object was just returned

        // but it can perform tests to figure it out
        Pilot pilot = p as Pilot;
        if (pilot != null)
        {
            // proceed with accessing Pilot-specific functionality
        }
    }
}
公共静态类PersonFactory
{
公共静态Person CreatePerson()
{
返回新人();
}
公共静态雇员CreateEmployee()
{
返回新员工();
}
公共静态导频CreatePilot()
{
返回新飞行员();
}
公共静态T CreatePerson()
式中T:人
{
返回(T)CreatePerson(类型(T));
}
公共静态人员CreatePerson(类型)
{
如果(类型==类型(人))
返回CreatePerson();
else if(类型==类型(员工))
返回CreateEmployee();
否则如果(类型==类型(飞行员))
返回CreatePilot();
其他的
抛出新ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture,“无法识别的类型[{0}]”,type.FullName),“类型”);
}
公共静态Person CreatePerson(字符串类型Person)
{
开关(个人类型)
{
案例“雇员”:
返回CreateEmployee();
“试点”案例:
返回CreatePilot();
违约:
返回CreateEmployee();
}
}
}
类UsageExample
{
Person GetPerson()
{
飞行员p;
p=(Pilot)PersonFactory.CreatePerson(“Pilot”);//这段代码已经知道需要一个Pilot,所以为什么不直接调用CreatePilot或CreatePerson()?
p=PersonFactory.CreatePilot();
p=PersonFactory.CreatePerson();
返回p;
}
Person GetPerson(类型personType)
{
Person p=PersonFactory.CreatePerson(personType);
//这段代码无法知道刚刚创建了什么类型的人,因为它取决于参数
返回p;
}
void KnowledgableCaller()
{
类型personType=类型(飞行员);
Person p=这个.GetPerson(typeof(Pilot));
//这段代码知道刚刚返回的Person对象应该是Pilot类型
飞行员飞行员=(飞行员)p;
//继续访问特定于飞行员的功能
}
void IgnorantCaller()
{
Person p=this.GetPerson();
//此调用方不知道刚刚返回的Person对象的类型
//但它可以进行测试来找出答案
先导=p为先导;
if(pilot!=null)
{
//继续访问特定于飞行员的功能
}
}
}

仅响应单词“DTO映射器”:泛型在这种情况下可能有效。我基本上有一个数据库表,每个类型层次结构有一个表。让我们假设一个带有“PersonType”字段的Person位置。和另一个包含“飞行员”特定信息的表格。要获得人员的结果集,if将遍历数据库行列表,如果是“Pilot”类型,则加载Pilot表信息,如果是“Employee”类型,则加载该特定信息。但是,不要将pilot内容加载到employee对象中……这会让它更清晰吗?谢谢!我喜欢IgnorantCaller方法。我可能可以使用它!我将从每个类型的表中加载一组记录,每个层次结构的表。如果此人的“PersonType”中有一个“pilot”'列,然后从先导表中加载先导编号。如果行在PersonType字段中有“Employee”类型,则不加载飞行员编号。。“马特·格里尔,你能再详细解释一下吗?”对象在实现上有所不同,而不是接口'-->这如何适用于这种情况?@Zortkun它之所以适用,是因为只有Pilot