类似工厂的模式,无需手动将鉴别器写入工厂

时间:2014-02-11 15:23:15

标签: c# nhibernate fluent-nhibernate

我有以下内容:

public abstract class FooBase
{
    public virtual int Id { get; set; }
}

public class Foo1 : FooBase { /* could be stuff here */ }

public class Foo2 : FooBase { /* could be stuff here */ }

public class Bar
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual SOMETHING WhichFoo { get; set } 
}

...其中WhichFoo处理FooBase使用string "Foo1" public class FooBaseMap : ClassMap<FooBase> { public FooBaseMap() { this.Id(x => x.Id); this.DiscriminateSubClassesOnColumn("Type"); } } public class Foo1Map : SubclassMap<Foo1> { public Foo1Map() { this.DiscriminatorValue("Foo1"); } } public class Foo2Map : SubclassMap<Foo2> { public Foo2Map() { this.DiscriminatorValue("Foo2"); } } 但这看起来非常混乱。

使用映射:

Foo

我希望能够根据Bar中存储的值创建新的Bar bar = this.Session.Get<Bar>(1); FooBase foo1 = bar.GetANewFoo(); // returns a new Foo1 Bar anotherBar = this.Session.Get<Bar>(123); FooBase foo2 = bar.GetANewFoo(); // returns a new Foo2 ,1或2。所以:

GetANewFoo()

Foo1可以是一个方法,一个返回Foo2FooBase的空实例的属性。

实际上我想要做的是在GetANewFoo中存储Bar要创建的"Foo1"类型。

当我创建一个时,没有明确地手动"Foo2"Bar写入{{1}},最好的方法是什么?

2 个答案:

答案 0 :(得分:0)

您可以在Bar表中创建一个列,它将保存它的Foo类型。因此,如果此SOMETHING类型的属性为enumstringint(无论如何),您可以使用switch-case statement来识别Foo,创造你需要的东西并回归。

就像这样:

    public FooBase GetANewFoo()
    {
        switch (WhichFoo)
        {
            case "Foo1": return new Foo1();
            case "Foo2": return new Foo2();
            default: return null;
        }
    }

答案 1 :(得分:0)

好吧,我想我明白了 - 实际上是rehashing a method I used for the Strategy Pattern

public abstract class FooFactoryBase
{
    protected FooFactoryBase() { } // for NHibernate

    protected FooFactoryBase(Guid id)
    {
        this.Id = id;
    }

    public virtual Guid Id { get; set; }
    public virtual IList<Bar> Bars { get; set; }
    public abstract FooBase CreateFoo();
}

public class Foo1Factory : FooFactoryBase
{
    public readonly static Guid Guid = new Guid("abc123...");

    public Foo1Factory() : base(Guid) { }

    public override FooBase CreateFoo()
    {
        return new Foo1();
    }
}

然后Bar成为:

public class Bar
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual FooFactoryBase FooFactory { get; set; }
}

并映射:

public class BarMap : ClassMap<Bar>
{
    this.Id(x => x.Id);
    this.Map(x => x.Name);
    this.References(x => x.FooFactory);
}

public class FooFactoryBaseMap : ClassMap<FooFactoryBase>
{
    this.Id(x => x.Id);
    this.HasMany(x => x.Bars).Inverse();
    this.DiscriminateSubClassesOnColumn("Id");
}

public class Foo1FactoryMap : SubClassMap<Foo1Factory>
{
    this.DiscriminatorValue(Foo1Factory.Guid);
}

现在,当我创建数据库时,我可以使用FooFactory来填充它,添加Bars时我可以从数据库中加载适当的Factory,然后调用我的代码这样:

Bar bar = this.Session.Get<Bar>(10);

FooBase foo = bar.FooFactory.CreateFoo();

将创建相应的FooBase

有时你只需要问这个问题就可以解决:)