我正在使用 Unity 来解析 Mike Hadlow 的通用存储库实现(linq to sql 风格)定位多个数据库。有效的容器配置:
container.RegisterType<IConnectionStringProvider, HistoryConnectionProvider>(new TransientLifetimeManager())
.RegisterType<IConnectionStringProvider, MetaConnectionProvider>("meta", new TransientLifetimeManager())
.RegisterType<IDataContextProvider, DataContextProvider>(new TransientLifetimeManager())
.RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IConnectionStringProvider>("meta")))
// this registration of Repository<> resolves the history database by default
.RegisterType(typeof(IRepository<>), typeof(Repository<>), new TransientLifetimeManager());
// anything not targeting this database has to be declared
.RegisterType<IRepository<SpecificType>, Repository<SpecificType>>(new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<DataContextProvider>("meta")));
这似乎不必要地冗长。所以我目前正在尝试不同的方法。为每个数据库使用单独的接口:
IConnectionStringProvider historyConnectionProvider = new ConnectionProvider(connections.HistoryConnectionString);
IConnectionStringProvider metaConnectionProvider = new ConnectionProvider(connections.MetaConnectionString);
container.RegisterType<IDataContextProvider, DataContextProvider>("history", new TransientLifetimeManager(), new InjectionConstructor(historyConnectionProvider))
.RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(metaConnectionProvider))
.RegisterType(typeof(IHistoryRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("history")))
.RegisterType(typeof(IMetaRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("meta")));
不幸的是,这不起作用。结果是注册的最后一个类型的 IDataContextProvider 被注入到每种类型的存储库中。预先感谢您的任何帮助。
I'm using Unity to resolve Mike Hadlow's implementation of generic repositories (linq to sql flavor) targeting multiple databases. The container configuration that works:
container.RegisterType<IConnectionStringProvider, HistoryConnectionProvider>(new TransientLifetimeManager())
.RegisterType<IConnectionStringProvider, MetaConnectionProvider>("meta", new TransientLifetimeManager())
.RegisterType<IDataContextProvider, DataContextProvider>(new TransientLifetimeManager())
.RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IConnectionStringProvider>("meta")))
// this registration of Repository<> resolves the history database by default
.RegisterType(typeof(IRepository<>), typeof(Repository<>), new TransientLifetimeManager());
// anything not targeting this database has to be declared
.RegisterType<IRepository<SpecificType>, Repository<SpecificType>>(new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<DataContextProvider>("meta")));
This seems unnecessarily verbose. So I'm currently trying different approaches. Using individual interfaces for each database:
IConnectionStringProvider historyConnectionProvider = new ConnectionProvider(connections.HistoryConnectionString);
IConnectionStringProvider metaConnectionProvider = new ConnectionProvider(connections.MetaConnectionString);
container.RegisterType<IDataContextProvider, DataContextProvider>("history", new TransientLifetimeManager(), new InjectionConstructor(historyConnectionProvider))
.RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(metaConnectionProvider))
.RegisterType(typeof(IHistoryRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("history")))
.RegisterType(typeof(IMetaRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("meta")));
Unfortunately, this doesn't work. The result is the last type of IDataContextProvider registered getting injected into every type of Repository. Thanks in advance for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
大牛,在第二组代码中,命名单独注册的目的是什么?您已经决定为每个数据库提供单独的接口,因此似乎也不需要为其指定名称。不过我可能会误解。此外,在第二个示例中,如果 Respository 可以实现 IMeta 和 IHistory 的接口,那么这就引出了两者之间有什么区别的问题。
如果我给你示例代码如何实现你想要的,它看起来与你的第一个示例非常相似,实际上并不比后者更冗长。
Daniel, on the second set of code what is the purpose of naming the separate registrations? You already have decided to have separate interfaces for each database so there doesn't seem to be a need to have a name on it as well. I could be misunderstanding though. Moreover, in the second example, if Respository can fulfill the interface for both IMeta and IHistory, then it begs the question what is the difference between the two.
Had i given you example code how to achieve what you want, it would look very similar to the first example you had which in reality isn't all that much more verbose than the latter.
原始问题的解决方案
Unity 需要独特的类型和界面。我仍然不确定为什么构造函数注入不能处理这个问题。这是有效的:
不幸的是,这设置了一种情况,即消费类需要了解其数据来自何处,对此我不满意。
更好的设计
我想保留生成的 dbml(因此这排除了使我的模型遵循特定接口的可能性),所以我只是将它们放入不同的子文件夹中,导致设计器为它们生成不同的命名空间每个数据库。
然后,在我的存储库实现中,我执行了以下操作:
我认为过去的一步是为统一构建一个自定义类型解析器来检查命名空间并返回注入数据上下文(这在工作单元之前是必要的)可以实施)。我不会将此标记为答案,以防有人有更好的解决方案。
Solution to the original question
Unity needed a unique type, as well as interface. I'm still unsure as to why constructor injection didn't handle this. This works:
Unfortunately, this sets up a situation where consuming classes need knowledge of where their data is coming from, which I wasn't happy with.
Better Design
I wanted to leave my dbmls generated (so this ruled out making my models adhere to a certain interface), so I just threw them in different sub folders, causing the designer to generate a different namespace for each database.
Then, in my Repository implementation, I did the following:
I think one step past this would be to build a custom type resolver for unity to check the namespace for me and return to injecting the data context (this will be necessary before unit of work can be implemented). I'm not going to mark this as the answer quite yet in case someone has a better solution.