对具有 list<interface<T>> 属性的类使用依赖注入,其中 T 未知

Posted

技术标签:

【中文标题】对具有 list<interface<T>> 属性的类使用依赖注入,其中 T 未知【英文标题】:Using dependency injection on a class with a list<interface<T>> property where T is unknown 【发布时间】:2013-11-21 05:20:41 【问题描述】:

请考虑以下场景...

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

因此,我有一个 ProductType 的概念,它有一个 List&lt;&gt; 属性,其中包含不同字段的元素 (AttributeField&lt;T&gt;)。

AttributeField&lt;T&gt; 具有用于不同值的 List&lt;&gt; 属性 (AttributeValue&lt;T&gt;)。

然后一个产品有一个 ProductType 来定义可用字段 (AttributeField&lt;T&gt;) 和一个 List&lt;AttributeValue&lt;?&gt;&gt; 来定义这个特定产品的值。

我正在尝试在 C# 中实现这个概念。我已经为接口和对象定义了结构,但正在努力使用 Fluent NHibernate 映射对象,大概是因为 ProductType 不是泛型类但具有泛型属性(List&lt;AttributeField&lt;T&gt;&gt; 其中 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; 

类 > 属性字段

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

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

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

类 > 属性值映射

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&lt;ProductType&gt; 对上述内容进行单元测试时,我收到以下错误:

单元测试适配器抛出异常: 成员 '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】:

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

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

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

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

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

【讨论】:

以上是关于对具有 list<interface<T>> 属性的类使用依赖注入,其中 T 未知的主要内容,如果未能解决你的问题,请参考以下文章

IList与List的区别

Attempt to invoke interface method 'boolean java.util.List.add(java.lang.Object)' on a null

返回具有 List<t> 中不存在的项目的 List<t> [重复]

Autowire List<List<String>> 超出具有未知键长度的属性文件

Could not instantiate bean class [java.util.List]: Specified class is an interface] with root cause(

如何检查 List<T> 元素是不是包含具有特定属性值的项目