对具有 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<>
属性,其中包含不同字段的元素 (AttributeField<T>
)。
AttributeField<T>
具有用于不同值的 List<>
属性 (AttributeValue<T>
)。
然后一个产品有一个 ProductType
来定义可用字段 (AttributeField<T>
) 和一个 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;
类 > 属性字段
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<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】:Fluent NHibernate 是一个对象关系映射器和持久性解决方案。它不是依赖注入容器。
通过数据库模式的可见性给出具体答案会容易得多。但是我知道这可能不切实际。
在我看来,您正在尝试使用 Fluent NHibernate 创建应用程序对象,而不是仅仅依靠它来实现持久性。这可能会导致一些非常复杂的映射作为 ORM 的一部分,这可能会导致很多映射类。如此处所述,您需要为泛型中的每个具体类型创建一个映射类:Map generic EntityBase<TEntity> class with FluentNHibernate 因此,我认为您的示例需要为每个 IAttributeField<T>
和每个 IAttributeValue<T>
提供一个映射类
我会尝试尽可能简化映射类以匹配您的数据模型,并使用带有一些工厂或 AutoMapper 的服务层来构造您的应用程序对象。并不总是建议将持久实体与应用程序分开(因为它会增加不必要的层和复杂性 - 通心粉代码),但在这种情况下,它似乎是必要的。
正如我所说,最好从数据模型开始并向外工作,并确保您了解 Fluent NHibernate 只是一个具有许多强大功能的 ORM
【讨论】:
以上是关于对具有 list<interface<T>> 属性的类使用依赖注入,其中 T 未知的主要内容,如果未能解决你的问题,请参考以下文章
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(