NHibernate 中具有不同类型答案的问题
我正在尝试找到一个问卷问题的简洁解决方案。假设我有一个 Questionnaire
类,其中包含 Answer
的集合,例如,
public class Questionnaire
{
public virtual ISet<Answer> Answers {get;set;}
}
根据问题,答案需要具有不同类型,例如出生日期、标记十分之一,你认为为什么等等。
我的第一个想法是这样的:
public class Question
{
public virtual QuestionType TypeOfQuestion {get;set;}
public virtual string PromptText {get;set;}
}
public class Answer
{
public virtual Question Question {get;set;}
}
public class DateTimeAnswer : Answer
{
public virtual DateTime Response {get;set;}
}
public class IntegerAnswer : Answer
{
public virtual int Response {get;set;}
}
// etc.
明显的问题是,从调查问卷来看,无法访问 Response
属性:
questionnaire.Answers[0].Response; // compile error
这同样适用于界面。使用通用接口会更好,例如:
public interface IAnswer<T>
{
public virtual Question Question {get;set;}
public virtual T Response {get;set;}
}
public class DateTimeAnswer : IAnswer<DateTime> {}
问题出现在 Questionnaire
类中,因为必须提供 IAnswer 的类型:
public class Questionnaire
{
public virtual ISet<IAnswer<???>> Answers {get;set;}
}
显然我不想有很多 IAnswer 集合每个都有不同的类型。我可以使用
ISet<IAnswer<dynamic>>
,但 NHibernate 不会喜欢它。
我意识到某些地方需要妥协,但我不确定哪个是最漂亮的。你会怎么办?
I'm trying to find a tidy solution to a questionnaire problem. Let us say that I have a Questionnaire
class which has a collection of Answer
s, e.g.
public class Questionnaire
{
public virtual ISet<Answer> Answers {get;set;}
}
Answers need to be of different types depending on the question, e.g. date of birth, marks out of ten, why do you think etc.
My first thought was something like this:
public class Question
{
public virtual QuestionType TypeOfQuestion {get;set;}
public virtual string PromptText {get;set;}
}
public class Answer
{
public virtual Question Question {get;set;}
}
public class DateTimeAnswer : Answer
{
public virtual DateTime Response {get;set;}
}
public class IntegerAnswer : Answer
{
public virtual int Response {get;set;}
}
// etc.
The obvious problem would be that from the questionnaire, there is no access to the Response
property:
questionnaire.Answers[0].Response; // compile error
The same would apply to an interface. It would be nicer to use a generic interface, such as:
public interface IAnswer<T>
{
public virtual Question Question {get;set;}
public virtual T Response {get;set;}
}
public class DateTimeAnswer : IAnswer<DateTime> {}
The problem then comes in the Questionnaire
class, as the type of IAnswer must be supplied:
public class Questionnaire
{
public virtual ISet<IAnswer<???>> Answers {get;set;}
}
Clearly I don't want to have many collections of IAnswer each with different types. I could use
ISet<IAnswer<dynamic>>
but then NHibernate wouldn't like it.
I realise a compromise is needed somewhere, but I'm not sure which is the prettiest. What would you do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为子类化问题和答案是一个很好的计划 - 摆脱 QuestionType 枚举。
然后,您可以在 Question 上使用 MakeAnswer(string) 抽象方法,它为您封装了很多逻辑,并且可以在必要时进行类型转换等。
我对Rob的回答 会是这样的:
其中
IAnswerFormatter
看起来像这样:并且 DateTimeAnswer 看起来像这样:
并且 DateTimeQuestion 可能看起来像:
这样你的答案就可以以自己的方式保存值,并且你 NH映射可以指定它在数据库中的外观(我建议使用鉴别器进行映射)您的问题可以负责从通用响应中创建答案。
I think subclassing Question as well as answer is a good plan - get rid of that QuestionType enum.
You can then have a MakeAnswer(string) abstract method on Question which encapsulates a lot of logic for you, and can do type conversion etc if necessary.
My solution to the generic problem on Rob's answer would be something like this:
Where
IAnswerFormatter
looks something like this:And DateTimeAnswer would look like this:
And DateTimeQuestion might look like:
This way your answer can hold the value in their own way, and you NH mappings can specify how it looks in the database (I'd recommend mapping using Discriminators) your Question can be responsible for creating answers from generic responses.
有趣的问题..
我的评论/想法:
QuestionType
枚举!ISet
- 我认为它不会增加任何价值..我会沿着这样的思路思考:
这里的想法是,我们需要了解本质您正在对所有对象执行操作,这可能只是显示答案。我们通过泛型添加类型安全性,这样我们就可以确保在没有类型参数的情况下无法创建新响应..
然后我们可以非常确定输入和输出的内容仅限于我们实现的答案类型。 NHib 处理这个问题应该没有真正的问题,因为它知道自己需要什么。
虽然这很糟糕,但我们从集合中返回了“
object
”版本的Answer
,这就是集合, >答案。这有帮助吗? :)
Interesting Problem..
My comments/thoughts:
QuestionType
enum!ISet<T>
- I don't think it adds any value..I would be thinking along the lines of something like:
The idea being here, we need to get to the essence of what you are doing to ALL of the objects, which is likely just displaying the answer.. We add type safety by way of generics so we can be sure that we can't create new responses without a type parameter..
We can then be pretty sure that what is going in and coming out is confined to the types of answers that we implement. NHib should have no real problem dealing with this since it knows what it needs.
While it sucks we have the "
object
" version of theAnswer
coming back from the collection, that is the what the collection is, Answers.Does this help? :)
将答案存储在完整的数据模型中真的有意义吗?你要和他们一起做什么?
最有可能的候选者似乎是报告,在这种情况下您可能需要研究 CQRS(命令查询职责分离)样式。相反,您将拥有一个 QuestionnaireCompletedCommand,其中包含答案列表,然后您将以某种方式坚持下去,以便可以针对它们运行报告。
当您拥有业务逻辑(您可能会这样做)时,数据模型非常有用,但如果您没有任何业务逻辑,您可能只会使解决方案变得不必要的复杂化。说到复杂化,当我说查看 CQRS 时,我不一定指的是事件溯源部分。这是一个巨大的并发症,很少有人需要。
Does it really make sense to store the answers in a full on data model? What are you going to be doing with them?
The most likely candidate seems to be reporting in which case you may want to look into the CQRS (Command Query Responsibility Separation) style. You would instead have a QuestionnaireCompletedCommand which would contain a list of answers you would then persist in some way that a reports could be ran against them.
Data models are great when you have business logic (which you might) but if you don't have any business logic you are likely just unnecessarily complicating the solution. Speaking of complicating when I say look at CQRS I don't necessarily mean the event sourcing part. That is a huge complication that very few people need.