对具有列表<接口<T>>属性,其中T是未知的



请考虑以下场景。。。

我有定义不同类型产品的对象,以及描述该产品所需的特性(例如,电视与香水具有不同的属性等)。

因此,我有ProductType的概念,它具有List<>性质,具有不同字段的元素(AttributeField<T>)。

对于不同的值(AttributeValue<T>),AttributeField<T>具有List<>特性。

然后,产品具有用于定义可用字段(AttributeField<T>)的ProductType和用于该特定产品的值的List<AttributeValue<?>>

我正试图在C#中实现这个概念。我已经为接口和对象定义了结构,但很难使用Fluent NHibernate映射对象,大概是因为ProductType不是泛型类,而是具有泛型属性(List<AttributeField<T>>,其中T可以是任何东西)。

界面>IProductType

public interface IProductType
{
    Guid Id { get; set; }
    string Name { get; set; }
    List<IAttributeField> Fields { get; set; }
}

接口>IAttributeField/IAttributeField

public interface IAttributeField
{
    Guid Id { get; set; }
    string Name { get; set; }
    IProductType ProductType { get; set; }
}
public interface IAttributeField<T> : IAttributeField
{
    Guid Id { get; set; }
    string Name { get; set; }
    List<IAttributeValue<T>> Values { get; set; }
    IProductType ProductType { get; set; }
}

接口>IAttributeValue

public interface IAttributeValue<T>
{
    Guid Id { get; set; }
    T Value { get; set; }
    IAttributeField<T> Field { get; set; }
}

类别>产品类型

public class ProductType : IProductType
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<IAttributeField> Fields { get; set; }
}

类别>AttributeField

public class AttributeField<T> : IAttributeField<T>
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<IAttributeValue<T>> Values { get; set; }
    public IProductType ProductType { get; set; }
}

类别>属性值

public class AttributeValue<T> : IAttributeValue<T>
{
    public Guid Id { get; set; }
    public T Value { get; set; }
    public IAttributeField<T> Field { get; set; }
}

我正在使用Fluent NHibernate for ORM和SQL 2008数据库,并具有以下映射类:

类别>产品类型映射

public class ProductTypeMapping : ClassMap<IProductType>
{
    public ProductTypeMapping()
    {
        Not.LazyLoad();
        Id(x => x.Id).GeneratedBy.GuidNative();
        Map(x => x.Name).Length(50).Not.Nullable();
        HasMany(x => x.Fields).CollectionType<IAttributeField>();
    }
}

类别>AttributeFieldMapping

public class GenericAttributeFieldMapping : ClassMap<IAttributeField>
{
    public GenericAttributeFieldMapping()
    {
        Not.LazyLoad();
        Id(x => x.Id);
        Map(x => x.Name).Length(50).Not.Nullable();
        References(x => x.ProductType).Cascade.All();
    }
}
public class AttributeFieldMapping<T> : ClassMap<IAttributeField<T>>
{
    public AttributeFieldMapping()
    {
        Not.LazyLoad();
        Id(x => x.Id).GeneratedBy.GuidNative();
        Map(x => x.Name).Length(50).Not.Nullable();
        HasMany(x => x.Values).Cascade.AllDeleteOrphan();
        References(x => x.ProductType).Cascade.All();
    }
}

类别>AttributeValueMapping

public class AttributeValueMapping<T> : ClassMap<IAttributeValue<T>>
{
    public AttributeValueMapping()
    {
        Not.LazyLoad();
        Id(x => x.Id).GeneratedBy.GuidNative();
        Map(x => x.Value).CustomType<T>();
        References(x => x.Field).Cascade.All();
    }
}

当我尝试用new PersitenceSpecification<ProductType>对上面的内容进行单元测试时,我会得到以下错误:

单元测试适配器引发异常:未解析成员"FluentHibernate。Cfg。FluentConfiguration Exception,FluentHibernate,Version=1.3.0.733,Culture=neutral,PublicKeyToken=8aa435e3cb308880"的类型

当进一步调试时,我得到以下异常消息:

没有持久性:System.Collections.Generic.List`1[[Models.Interfaces.AttributeField,Models,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null]]

大概这是因为我不能使用泛型类型进行映射,并且需要为每个要映射的泛型类型提供映射。

我如何让上面详述的结构与依赖注入和ORM一起工作,而不必显式地为每个泛型类型提供映射,或者在提供具有不同属性(字段和值)的模型的灵活性的同时,可以对我的ORM工作方法进行哪些更改?

Fluent NHibernate是一个对象关系映射器和持久性解决方案。它不是依赖项注入容器。

有了数据库模式的可见性,给出一个具体的答案会容易得多。然而,我理解这可能并不实际。

在我看来,您正试图使用Fluent NHibernate创建应用程序对象,而不仅仅是依靠它来实现持久性。这可能会导致一些非常复杂的映射作为ORM的一部分,这可能会产生很多映射类。如前所述,您需要为泛型中的每个具体类型提供一个映射类:Map generic EntityBase<TEntity>用FluentHibernate类所以这是你的例子,我认为你需要为每个IAttributeField<T>和每个IAttributeValue<T> 一个

我会尽量简化映射类,以匹配您的数据模型,并使用带有一些工厂或AutoMapper的服务层来构建您的应用程序对象。并不总是建议将持久化实体与应用程序分离(因为这可能会添加不必要的层和复杂性——Macaroni代码),但在这种情况下,这似乎是必要的。

正如我所说,从数据模型开始,向外工作是最好的,并确保您理解Fluent NHibernate只是一个具有许多强大功能的ORM

最新更新