【问题标题】:Resolving injected instances when using Activator.CreateInstance使用 Activator.CreateInstance 时解析注入的实例
【发布时间】:2011-02-06 20:58:13
【问题描述】:

我试图弄清楚如何让 Castle Windsor 解决使用 Activator.CreateInstance 创建的对象的依赖关系。

目前,当我以这种方式创建对象时,创建的对象内部的依赖关系没有得到解决。我已经四处搜索,看看是否有一个 Windsor 方法可以做同样的事情,同时也解决依赖关系,但到目前为止我还没有找到任何东西。

至于我为什么要以这种方式创建实例,我正在玩一个基本的文本游戏以获得一点乐趣,并且实例是根据用户输入命令创建的,因此我需要根据一个字符串(目前该命令在 Dictionary 中映射到一个类型,然后使用上述方法创建)。

感谢所有帮助。

【问题讨论】:

  • 为什么不使用 Windsor 解决对象,而不是首先使用 Activator.CreateInstance?
  • 我现在正在做。请参阅下面的答案以了解我目前的实施情况。

标签: c# dependency-injection inversion-of-control castle-windsor createinstance


【解决方案1】:

AFAIK 您可以在城堡温莎注册,或者您可以注册所谓的“命名实例”,这样您就可以通过容器解析它们来创建您需要的对象,而无需处理肯定无法执行 IoC 的 Activator.CreateInstance。 基本上你必须用一个键注册你的组件:

AddComponent(String key, Type classType) 

然后调用

Resolve(string Key)

让您的组件正确创建并解决所有依赖关系。

【讨论】:

  • 感谢 Felice,您的回答真的很有帮助!我将在下面发布我的最终解决方案作为另一个答案,并将您的答案设置为接受的答案。为正确方向的帮助和推动而欢呼。
【解决方案2】:

为了扩展 Felice 给出的答案,我认为根据接受的答案发布我得出的解决方案会很有用。

目前我的命令是通过IDictionary<TKey,TValue> 映射的,但很快就会转移到另一种媒体(XML、JSON 等)。

以下是我为用户输入命令注册组件的方式:

public void InstallUserCommands(IWindsorContainer container)
{

  var commandToClassMappings = new Dictionary<string, string>
                            {
                              {"move", "MoveCommand"},
                              {"locate","LocateSelfCommand"},
                              {"lookaround","LookAroundCommand"},
                              {"bag","LookInBagCommand"}
                            };

  foreach (var command in commandToClassMappings)
  {
     var commandType = Type.GetType("TheGrid.Commands.UserInputCommands." + command.Value);
     container.Register(Component.For(commandType).Named(command.Key));

  }
}

并解析实例:

public UserCommandInputMapperResponse Invoke(UserCommandInputMapperRequest request)
{
  var container = new WindsorContainer();
  container.Install(FromAssembly.This());

  IUserInputCommand instance;

  try
  {
    instance = container.Resolve<IUserInputCommand>(request.CommandName.ToLower().Trim());
  }
  catch (Exception)
  {
     instance = null;
   }

   return new UserCommandInputMapperResponse
                {
                   CommandInstance = instance
                };
}

【讨论】:

    【解决方案3】:

    Windsor 的一个更好的实现方式是使用类型化工厂。使用类型化工厂,您的代码不必引用容器,因为会自动为您创建工厂实现。

    使用类型化工厂,您的工厂可能如下所示:

    public interface IUserInputCommandFactory
    {
        IUserInputCommand GetMove();
        IUserInputCommand GetLocate();
        IUserInputCommand GetLookAround();
        IUserInputCommand GetBag();
    }
    

    Windsor 会将每个工厂方法转发给相应的解析 - 例如GetMove 将变为 container.Resolve&lt;IUserInputCommand&gt;("Move")。

    更多信息请参见typed factory docs ("'get' methods lookup by name)。

    我认为这是温莎真正闪耀的地方之一 :)

    【讨论】:

    • 哦,谢谢 Mogens。看起来棒极了。明天我会进一步看看这个。为帮助干杯!
    猜你喜欢
    • 2013-07-18
    • 2017-08-11
    • 1970-01-01
    • 2012-02-25
    • 2021-05-10
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多