C# 如何解决控制器操作的类型依赖关系?

C# 如何解决控制器操作的类型依赖关系?,c#,dependency-injection,inversion-of-control,unity-container,asp.net-mvc-5,C#,Dependency Injection,Inversion Of Control,Unity Container,Asp.net Mvc 5,更新 我成功地创造了一些令人满意的东西。您可以看到代码的相关部分。如果有什么我可以改进的,请告诉我。我有种唠叨的感觉,这不是很有效 澄清 正如d_z所建议的那样,它显然可以处理静态依赖关系,但我希望,为了避免实例化未使用的对象,我可以使用类似的方法: public class HomeController : Controller { [Dependency] protected IBaseData ActionData { get; set; } public ActionRes

更新

我成功地创造了一些令人满意的东西。您可以看到代码的相关部分。如果有什么我可以改进的,请告诉我。我有种唠叨的感觉,这不是很有效

澄清

正如
d_z
所建议的那样,它显然可以处理静态依赖关系,但我希望,为了避免实例化未使用的对象,我可以使用类似的方法:

public class HomeController : Controller
{
  [Dependency]
  protected IBaseData ActionData { get; set; }

  public ActionResult Index()
  {
    return View(ActionData);
  }

  public ActionResult About()
  {
    return View(ActionData);
  }
}
实际上,
IndexData
AboutData
实例中的数据不是静态的。实例属性是使用数据库中的数据设置的。DbProvider被注入到这些类中

最后,我想要的是最小化内存占用和数据库访问

原创

假设我们有以下基本控制器(带有相应的视图):

我们还有两个具有相同接口的类:

public class IndexData : IBaseData
{
  public string Name { get; set; }
  public string Index { get; set; }

  public IndexData()
  {
    Name = "Index";
    Index = "This is an Index instance";
  }
}

public class AboutData : IBaseData
{
  public string Name { get; set; }
  public string About { get; set; }

  public AboutData()
  {
    Name = "About";
    About = "This is an About instance";
  }
}

我想要的是Unity将这些类之一的实例注入到相应的视图中,具体取决于执行的操作。我一直想弄清楚如何做到这一点,但我被难住了。这可能吗?

要在Unity中为一个类型注册多个映射,您必须创建如下命名注册:

myContainer.RegisterType<IBaseData, IndexData>("Index");
myContainer.RegisterType<IBaseData, AboutData>("About");
[Dependency("Index")]
IBaseData data { get; set; }

看一看,要了解详情,你的要求毫无意义。依赖注入是关于注入(设计时)行为(又称服务)。然而,您试图做的是注入运行时数据。所以这不是IoC容器应该处理的任务


接下来,视图应该完全不知道任何依赖项注入。控制器应该从其操作方法返回视图所需的所有数据。确保您的
About
Index
操作方法返回正确的实例。

您能否举例说明希望如何在
HomeController
中使用这些类?当依赖项注入与您的应用程序行为相混淆时。无论您要调用哪个操作,DI都应该发生。您可以通过使用工厂、注入工厂并调用它来生成适当的数据来实现所需的功能class@Steven:它不在控制器中,我想使用它们。我想在视图中使用它们,从而使用依赖项注入将正确的模型绑定到正确的视图,将IndexData绑定到IndexView,将AboutData绑定到AboutView。@SimonHalsey:那么我的需求在DI中就不可能了?我应该坚持工厂模式?差不多。当您创建一个类(即您的控制器)的实例时,您应该能够使用该类上的任何方法或属性。如果你设计的类需要知道实例化时哪些方法可以/不能运行,那么你的设计很糟糕,要么使用工厂,要么将类拆分。我不同意IoC不应该处理运行时行为的说法。有时它非常有用,但是我认为它很少见。@ dz z:让容器注入运行时数据,使得有一个可验证的DI配置是非常困难的(甚至是不可能的)。无法在简单的集成测试或应用程序启动期间验证配置,将使配置非常脆弱,这意味着您必须单击整个应用程序以检查您的配置是否正确。我设法让它按我的喜好工作。我尽量听从你的建议。我用相关代码创建了一个。还有什么我可以改进的吗?@user3564235:在您的
UnityControllerFactory.CreateController
中,在出现异常时不要退回到调用基本行为,因为这样会隐藏真正的问题。为自己省下很多麻烦,让例外情况简单地冒出来。还可以防止存储库依赖于容器,从而导致服务定位器反模式。如果可能的话,还可以防止拥有实现共享行为或横切关注点的基类(BaseController)。仅仅为翻译建立一个基类似乎是不必要的,而且只会使事情变得复杂。今天早上醒来时,我有了新的见解,现在可以更清楚地看到事情了。无需注入
ActionViewModels
。事实上,从ActionViewModels中删除DI简化了
TranslationRepository
,并删除了它对IoC容器的依赖性。现在不需要配置Unity来解析不同的
ActionViewModels
,因为工厂创建了它们。单元测试也更容易实现,并且没有隐藏的依赖项。玩得好,先生,确实玩得好。虽然静态依赖项似乎有效,但它迫使我实例化每个xxxData类。这将对内存占用和数据库访问产生影响。(参见我编辑的问题)。然后使用
a data=myContainer.Resolve(“Index”):)我该怎么做/在哪里做?我没有对
myContainer
@user3564235的引用,要回答这个问题,我需要知道如何在默认的
UnityConfig
类中创建它:),该类是在添加
Unity bootstrapper for ASP.NET MVC
NuGet包(
Unity.MVC
)时创建的。除了添加的
RegisterType
s'之外,库存没有任何变化。
IBaseData data = myContainer.Resolve<IBaseData>("Index");
IBaseData data = myContainer.Resolve<IBaseData>("About");
[Dependency("Index")]
IBaseData data { get; set; }