Create a base fluent ordered constructor

2019-09-21 22:53发布

问题:

EDIT: Ok, seem example is unuseful...

I have an ordered fluent constructor that is common to many object (all have tha same properties). Is there a way to put all the code in the same base factory class and have only the final costructor in the derived factory?

I use constructor like this

.InitCreation()
.WithID()
.WithPoperty1()
.Create()

where only the Create() make the new object and ID is a mandatory field.

Generics seem me to need rewriting all methods in all factory, instead i want to rewrite only the Create() method to return the right object.

Other way is to grant mandatory field in fluent constructor without using an ordered fluent but don't find nothing to do it

EDIT2

The baseFactory:

    namespace FunzIA.DL.Factory
{
    public class BaseObjectFactory : IBaseObjectCreated, IBaseObjectWithMandatoryField1, IBaseObjectWithFields
{
    internal int mandatoryField1 { get; set; }
    internal string mandatoryField12 { get; set; }
    internal bool optionaField1 { get; set; }

    private BaseObjectFactory(){}

    public static IBaseObjectCreated InitCreation()
    {return new BaseObjectFactory(); }

    public IBaseObjectWithMandatoryField1 WithMandatoryField1(int number)
    {
        mandatoryField1 = number;
        return this;
    }

    public IBaseObjectWithFields ConmandatoryField12(string text)
    {
        mandatoryField12 = text;
        return this;
    }

    public IBaseObjectWithFields optionaField1(bool optionaField1P)
    {
        optionaField1 = optionaField1P;
        return this;
    }

    public BaseObject Create()
    {return new BaseObject(this);}
}



public interface IBaseObjectCreated
{IBaseObjectWithMandatoryField1 WithMandatoryField1(int number);}

public interface IBaseObjectWithMandatoryField1 
{IBaseObjectWithFields ConmandatoryField12(string text);}

public interface IBaseObjectWithFields
{
    IBaseObjectWithFields optionaField1(bool optionaField1);
    BaseObject Create();
}
}

The old Example

i create a class Struttura in this way:

namespace FunzIA.DL.Oggetti
{
public class Struttura
{
    public int IdStruttura { get; set; }
    public string Descrizione { get; set; }
    public bool Annullato { get; set; }

    private Struttura(){}
    public Struttura(StrutturaFactory factory)
    {
        IdStruttura = factory.idStruttura;
        Descrizione = factory.descrizione;
        Annullato = factory.annullato;
    }   
}
}

And his Fuent Constructori is this:

namespace FunzIA.DL.Factory
{
    public class StrutturaFactory : IStrutturaCeato, IStrutturaConChiave, IStrutturaConProprieta
{
    internal int idStruttura { get; set; }
    internal string descrizione { get; set; }
    internal bool annullato { get; set; }
    internal IList<Processo> processi { get; set; }

    private StrutturaFactory(){}

    public static IStrutturaCeato IniziaCreazione()
    {return new StrutturaFactory(); }

    public IStrutturaConChiave ConCodice(int codiceP)
    {
        idStruttura = codiceP;
        return this;
    }

    public IStrutturaConProprieta ConDescrizione(string nome)
    {
        descrizione = nome;
        return this;
    }

    public IStrutturaConProprieta Annullato(bool annullatoP)
    {
        annullato = annullatoP;
        return this;
    }

    public Struttura Crea()
    {return new Struttura(this);}
}



public interface IStrutturaCeato 
{IStrutturaConChiave ConCodice(int chiave);}

public interface IStrutturaConChiave 
{IStrutturaConProprieta ConDescrizione(string nome);}

public interface IStrutturaConProprieta
{
    IStrutturaConProprieta Annullato(bool annullato);
    IStrutturaConProprieta ConProcessi(IList<Processo> processi);
    Struttura Crea();
}
}

In this way i can write constructor in this way

Struttura actual = StrutturaFactory.IniziaCreazione()
                                .ConCodice(1)
                                .ConDescrizione("MiaDescrizione")
                                .Crea();

But now i see that i have many object with similar fields (ID, description, canceled) so i try to write a common fluent constructor:

namespace FunzIA.DL
{
public class OggettoBaseFactory : IOggettoBaseCeato, IOggettoBaseConChiave, IOggettoBaseConProprieta
{
    internal int id { get; set; }
    internal string descrizione { get; set; }
    internal bool annullato { get; set; }

    private OggettoBaseFactory(){}

    public static IOggettoBaseCeato IniziaCreazione()
    {return new OggettoBaseFactory();}

    public IOggettoBaseConChiave ConCodice(int codiceP)
    {
        id = codiceP;
        return this;
    }

    public IOggettoBaseConProprieta ConDescrizione(string nome)
    {
        descrizione = nome;
        return this;
    }

    public IOggettoBaseConProprieta Annullato(bool annullatoP)
    {
        annullato = annullatoP;
        return this;
    }

    public OggettoBase Crea()
    {return null;}
}



public interface IOggettoBaseCeato 
{IOggettoBaseConChiave ConCodice(int chiave);}

public interface IOggettoBaseConChiave 
{IOggettoBaseConProprieta ConDescrizione(string nome);}

public interface IOggettoBaseConProprieta
{
    IOggettoBaseConProprieta Annullato(bool annullato);
    OggettoBase Crea();
}
}

And modify my Factory

namespace FunzIA.DL.Factory
{
    public class StrutturaFactory : OggettoBaseFactory
    {
        public Struttura Crea()
        {return new Struttura(this);}
    }
}

But now when i write Struttura actual = StrutturaFactory.IniziaCreazione() .ConCodice(idExpected) .ConDescrizione(descrizioneExpected) .Annullato(annullatoExpected) .Crea();

i get this error:

Error 5 Cannot implicitly convert type 'FunzIA_DL.OggettoBase' to 'FunzIA.DL.Oggetti.Struttura'. An explicit conversion exists (are you missing a cast?)

Is there a way to do it or i have to rewrite the same logic in all my fluent constructor?

回答1:

Just cast it like this:

Struttura actual = (Struttura)StrutturaFactory.IniziaCreazione() .ConCodice(idExpected) .ConDescrizione(descrizioneExpected) .Annullato(annullatoExpected) .Crea();


回答2:

I solved using Generics in this way in the BaseFactory:

public T Create<T>()
        {
            return (T)Activator.CreateInstance(typeof(T), this);
        }

then my DerivedFactory is simply this:

namespace FunzIA.DL.Factory
{
    public class SocietyFactory : BaseFactory
    {}
}

so i can write

Society actual = SocietyFactory.InitCreation()
                    .WithCode(idExpected)
                    .Create<Societa>();