发布于 2024-12-19 09:49:26 字数 2311 浏览 1 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南汐寒笙箫 2024-12-26 09:49:26

大牛,在第二组代码中,命名单独注册的目的是什么?您已经决定为每个数据库提供单独的接口,因此似乎也不需要为其指定名称。不过我可能会误解。此外,在第二个示例中,如果 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.

坚持沉默 2024-12-26 09:49:26

原始问题的解决方案

Unity 需要独特的类型和界面。我仍然不确定为什么构造函数注入不能处理这个问题。这是有效的:

// where IMetaRepository<T> and MetaRepository<T> both are derived place holders
container.RegisterType(typeof(IMetaRepository<>), typeof(MetaRepository<>), new TransientLifetimeManager());

不幸的是,这设置了一种情况,即消费类需要了解其数据来自何处,对此我不满意。

更好的设计

我想保留生成的 dbml(因此这排除了使我的模型遵循特定接口的可能性),所以我只是将它们放入不同的子文件夹中,导致设计器为它们生成不同的命名空间每个数据库。

然后,在我的存储库实现中,我执行了以下操作:

public Repository(IConnections connections)
{
  T type = new T();
  var ns = type.GetType().Namespace;
  if (ns == "Project.Common.DAL.History")
  {
    _dataContext = new DataContext(connections.HistoryConnectionString);
  }
  else if (ns == "Project.Common.DAL.Transaction")
  {
    _dataContext = new DataContext(connections.TransactionConnectionString);
  }
  else
  {
    _dataContext = new DataContext(connections.MetaConnectionString);
  }
}

我认为过去的一步是为统一构建一个自定义类型解析器来检查命名空间并返回注入数据上下文(这在工作单元之前是必要的)可以实施)。我不会将此标记为答案,以防有人有更好的解决方案。

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:

// where IMetaRepository<T> and MetaRepository<T> both are derived place holders
container.RegisterType(typeof(IMetaRepository<>), typeof(MetaRepository<>), new TransientLifetimeManager());

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:

public Repository(IConnections connections)
{
  T type = new T();
  var ns = type.GetType().Namespace;
  if (ns == "Project.Common.DAL.History")
  {
    _dataContext = new DataContext(connections.HistoryConnectionString);
  }
  else if (ns == "Project.Common.DAL.Transaction")
  {
    _dataContext = new DataContext(connections.TransactionConnectionString);
  }
  else
  {
    _dataContext = new DataContext(connections.MetaConnectionString);
  }
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文