在具有列表<interface <t>&gt;的类上使用依赖项注入T未知的属性</interface <t>

时间:2013-11-21 05:20:42

标签: c# generics orm fluent-nhibernate

请考虑以下情况......

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

因此,我有ProductType的概念,其List<>属性包含不同字段(AttributeField<T>)的元素。

AttributeField<T>针对不同的值(List<>)具有AttributeValue<T>属性。

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

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

接口&gt; IProductType

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

接口&gt; 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; }
}

接口&gt; IAttributeValue

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

课程&gt; ProductType

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

课程&gt; 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; }
}

课程&gt;的AttributeValue

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数据库并具有以下映射类:

课程&gt; ProductTypeMapping

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>();
    }
}

课程&gt; 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();
    }
}

课程&gt; 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>对上述单元进行单元测试时,出现以下错误:

单元测试适配器抛出异常: 成员'FluentNHibernate.Cfg.FluentConfigurationException,FluentNHibernate,Version = 1.3.0.733,Culture = neutral,PublicKeyToken = 8aa435e3cb308880'

的类型未解析

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

通过数据库模式的可见性给出具体答案会容易得多。但是我知道这可能不实用。

听起来我正在尝试使用Fluent NHibernate创建应用程序对象,而不是仅仅依靠它来实现持久性。这可能会导致一些非常复杂的映射作为ORM的一部分,这可能会导致许多映射类。如此处所述,您需要为泛型中的每种具体类型设置一个映射类:Map generic EntityBase<TEntity> class with FluentNHibernate因此,我认为每个IAttributeField<T>和每个IAttributeValue<T>需要一个

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

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